Build Events Database

Fish

fish_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Events")
### Format events to schema
#change all empty columns from logical to character class
fish_events[sapply(fish_events, is.logical)] <- lapply(fish_events[sapply(fish_events, is.logical)],  as.character)
#change eventID to just the KANF value
fish_events$eventID<-str_extract(fish_events$eventID,"KANF\\d\\d\\d")
#round the lat/longs to four digits (~ 10m uncertainty)
fish_events$decimalLatitude<-round(as.numeric(fish_events$decimalLatitude),digits = 4)
fish_events$decimalLongitude<-round(as.numeric(fish_events$decimalLongitude),digits = 4)
fish_events$coordinateUncertaintyInMeters<-as.numeric(fish_events$coordinateUncertaintyInMeters) 
# class(fish_events$geoReferenceProtocol)
# class(fish_events$maximumDepthInMeters)
# class(fish_events$minimumDepthInMeters)
# class(fish_events$recordedBy) 
# class(fish_events$samplingProtocol) #some missing. ask Diane to fill this in
# class(fish_events$habitatBiotic)
#remove carriage returns from Geomorphological Zone
fish_events$habitatGeomorphologicalZone<-str_replace_all(fish_events$habitatGeomorphologicalZone,pattern="\r\n",replacement = "")
fish_events$habitatSubstrate<-str_replace_all(fish_events$habitatSubstrate,pattern="\r\n",replacement = "")
fish_events$year<-as.numeric(fish_events$year)
fish_events$month<-match(fish_events$month,month.abb)
fish_events$day<-as.numeric(fish_events$day)
#Recommended fields
# class(fish_events$eventRemarks)
# class(fish_events$locality)
# class(fish_events$eventRemarks)
# class(fish_events$verbatimCoordinates)
# class(fish_events$eventMedia)
#remove ending times from eventTime field
fish_events$eventTime<-str_extract(string=fish_events$eventTime,pattern="^\\d\\d:\\d\\d")

Algae

algae_events<-read_excel("/Users/eric/google_drive/MarineGEO/algae/MarineGEOHI_bioassessment_master_KANA.xlsx", sheet="Station")
### Format events to schema
#change all empty columns from logical to character class
algae_events[sapply(algae_events, is.logical)] <- lapply(algae_events[sapply(algae_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
algae_events$decimalLatitude<-round(as.numeric(algae_events$decimalLatitude),digits = 4)
algae_events$decimalLongitude<-abs(round(as.numeric(algae_events$decimalLongitude),digits = 4))*-1
# class(algae_events$eventID)
# class(algae_events$geoReferenceProtocol) #good
# class(algae_events$coordinateUncertaintyInMeters) #good
# class(algae_events$maximumDepthInMeters) #some missing. ask Melinda to fill this in
# class(algae_events$minimumDepthInMeters)#some missing. ask Melinda to fill this in
# class(algae_events$recordedBy) #some missing. ask Melinda to fill this in
# class(algae_events$samplingProtocol) #some missing. ask Melinda to fill this in
# class(algae_events$`habitatBiotic`)
# class(algae_events$`habitatGeomorphologicalZone`)
# class(algae_events$`habitatSubstrate`)
#Recommended fields
# class(algae_events$eventRemarks)
# class(algae_events$locality)
# class(algae_events$eventRemarks)
# class(algae_events$verbatimCoordinates)
# class(algae_events$eventMedia)
#format time correctly
algae_events$eventTime<-as.character(parse_date_time(algae_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")

Macroinvertebrates

invert_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Inverts/BKANE_063017_FIMS.xlsx", sheet = "Station", skip=2)
### Format events to schema
# Note: invert event data need a lot of cleaning, including importing stations from the algae and meiofauna team, and making new stations with "A" or "B" appended. Currently 839 samples do not have station information because of this.
# remove event fields that don't appear in the schema
invert_events<-invert_events[,-grep(pattern = "^X",x = names(invert_events),perl=T)]
#change all empty columns from logical to character class
invert_events[sapply(invert_events, is.logical)] <- lapply(invert_events[sapply(invert_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
invert_events$decimalLatitude<-round(as.numeric(invert_events$decimalLatitude),digits = 4)
invert_events$decimalLongitude<-abs(round(as.numeric(invert_events$decimalLongitude),digits = 4))*-1
invert_events$geoReferenceProtocol<-"GPS"
invert_events$coordinateUncertaintyInMeters<-100
# class(invert_events$maximumDepthInMeters) #some missing. ask John to fill this in
# class(invert_events$minimumDepthInMeters)#some missing. ask John to fill this in
#Format the date properly, get rid of the "raw" field
invert_events$day<-day(invert_events$eventDate)
invert_events$month<-month(invert_events$eventDate)
invert_events$year<-year(invert_events$eventDate)
invert_events$eventDate<-NULL
# class(invert_events$recordedBy) #good
# class(invert_events$samplingProtocol) #some missing. ask John to fill this in
# class(invert_events$habitatGeomorphologicalZone) #some missing. ask John to fill this in. #this needs to be aligned with the schema
# class(invert_events$habitatSubstrate) # some missing. ask John to fill this in. #this needs to be aligned with the schema
#Recommended fields
# class(invert_events$locality)
# class(invert_events$eventRemarks)

Meiofauna

meio_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Meiofauna/Hawaii2017_meiofauna_MarineGEO.xlsx", sheet = "station data", skip=1)
#remove columns that don't appear in MarineGEO schema
meio_events<-meio_events[,-grep(pattern = "^X",x = names(meio_events),perl=T)]
### Format events to schema
#Missing station KANM087!!!
#change all empty columns from logical to character class
meio_events[sapply(meio_events, is.logical)] <- lapply(meio_events[sapply(meio_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
meio_events$decimalLatitude<-round(as.numeric(meio_events$decimalLatitude),digits = 4)
meio_events$decimalLongitude<-abs(round(as.numeric(meio_events$decimalLongitude),digits = 4))*-1
meio_events$coordinateUncertaintyInMeters<-100
meio_events$minimumDepthInMeters<-as.numeric(meio_events$minimumDepthInMeters)
meio_events$maximumDepthInMeters<-as.numeric(meio_events$maximumDepthInMeters)
# class(meio_events$maximumDepthInMeters)
# class(meio_events$minimumDepthInMeters)
# class(meio_events$recordedBy) #ask Freya to follow format - add last names, and pipes between names
# class(meio_events$samplingProtocol) #some missing. ask Freya to fill this in
# class(meio_events$habitatGeomorphologicalZone) #some missing. ask Freya to fill this in
# class(meio_events$habitatSubstrate) # some missing. ask Freya to fill this in
# class(meio_events$habitatBiotic)
#Recommended fields
# class(meio_events$locality)
# class(meio_events$eventRemarks)
meio_events$day<-day(meio_events$eventDate)
meio_events$month<-month(meio_events$eventDate)
meio_events$year<-year(meio_events$eventDate)
meio_events$eventDate<-NULL
#format the $^#&* time correctly
meio_events$eventTime<-format(.POSIXct(86400*as.numeric(meio_events$eventTime), "UTC"), "%H:%M")
#meio_events$eventTime<-as.character(parse_date_time(meio_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")
meio_events$eventMedia<-"N"

ARMS

arms_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/ARMS/MarineGEOHI_bioassessment_master-ARMS.xlsx", sheet = "Station")
### Format events to schema
#change all empty columns from logical to character class
arms_events[sapply(arms_events, is.logical)] <- lapply(arms_events[sapply(arms_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
arms_events$decimalLatitude<-round(as.numeric(arms_events$decimalLatitude),digits = 4)
arms_events$decimalLongitude<-abs(round(as.numeric(arms_events$decimalLongitude),digits = 4))*-1
arms_events$coordinateUncertaintyInMeters<-10
arms_events$minimumDepthInMeters<-as.numeric(arms_events$minimumDepthInMeters)
# class(arms_events$geoReferenceProtocol)
# class(arms_events$eventID)
# class(arms_events$maximumDepthInMeters)
# class(arms_events$recordedBy) #ask Laetitia to follow name format
# class(arms_events$samplingProtocol)
# class(arms_events$habitatGeomorphologicalZone)
# class(arms_events$habitatSubstrate) 
# class(arms_events$habitatBiotic)
#Recommended fields
# class(arms_events$locality)
# class(arms_events$year)
# class(arms_events$month)
# class(arms_events$day)
arms_events$eventMedia<-"Y" #still need to get these from Laetitia

Visual Transects

trans_events<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/bioassessment_KANV.xlsx", sheet = "Station")
trans_event_photos<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/KANV_benthic-photos_filenames_20170711.xlsx", sheet = "Sheet1")
# event photos
#pop off the eventID into its own field
trans_event_photos$eventID<-sub(pattern="(KANV\\d\\d\\d)_.+",replacement = "\\1", trans_event_photos$eventMedia, perl=T)
#use ddply to lump all eventMedia into a single field, separated by a |
trans_eventMedia<-ddply(trans_event_photos, "eventID", transform, eventMedia = paste(eventMedia, collapse = "|"))
#keep only the first instance of each occurrenceID
trans_eventMedia<-trans_eventMedia[!duplicated(trans_eventMedia$eventID),]
#delete original eventMedia column and join on the new one
trans_events$eventMedia<-NULL
trans_events<-left_join(trans_events, trans_eventMedia, by="eventID")
### Format events to schema
#change all empty columns from logical to character class
trans_events[sapply(trans_events, is.logical)] <- lapply(trans_events[sapply(trans_events, is.logical)],  as.character)
#round to 4 decimal digits (~10m uncertainty) and meake sure longitude is negative
trans_events$decimalLatitude<-round(as.numeric(trans_events$decimalLatitude),digits = 4)
trans_events$decimalLongitude<-abs(round(as.numeric(trans_events$decimalLongitude),digits = 4))*-1
trans_events$minimumDepthInMeters<-as.numeric(trans_events$minimumDepthInMeters)
# class(trans_events$eventID)
# class(trans_events$coordinateUncertaintyInMeters)
# class(trans_events$maximumDepthInMeters)
# class(trans_events$recordedBy) 
# class(trans_events$samplingProtocol)
# class(trans_events$habitatGeomorphologicalZone)
# class(trans_events$habitatSubstrate)
# class(trans_events$habitatBiotic)
#Recommended fields
# class(trans_events$locality)
# class(trans_events$year)
# class(trans_events$month)
# class(trans_events$day)
trans_events$eventMedia<-"Y"
trans_events$eventTime<-as.character(parse_date_time(trans_events$eventTime, orders="ymdHMS", tz="HST"),format="%H:%M")

Join Events

events<-full_join(fish_events,algae_events)
events<-full_join(events,invert_events)
events<-full_join(events,meio_events)
events<-full_join(events,arms_events)
events<-full_join(events,trans_events)

Build sample databases

Fish

Import

# First go through and make sure all stations have Lat/Longs, or as many as possible. Delete secondary lat/longs
#read in the sample data, skipping first 3 lines of other headers. Format all times as hh:mm in Excel, paste into textwrangler if they need homogenization (i.e. multiple formats of times)
fish_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Samples")
fish_genetic<-read_excel(path="/Users/eric/google_drive/MarineGEO/Fish/FISH_DATA_21Jul2017.xlsx",sheet="Genetic samples")
#these commands apply to the original fish-group template
#remove columns without mapped DwC terms mapped
#fish_samples<-fish_samples[,-grep(pattern = "^X",x = names(fish_samples),perl=T)]
#fish_events<-fish_events[,-grep(pattern = "^X",x = names(fish_events),perl=T)]
#remove records without occurrenceIDs (temp before final dataset)
#fish_samples<-fish_samples[-which(is.na(fish_samples$occurrenceID)),]
#translate fieldIDs to eventIDs
#fish_samples$eventID<-gsub("LRP 17-","KANF0",fish_samples$eventID)
#use ddply to lump all materialSampleIDs into a single field, separated by a |
#fish_samples<-ddply(fish_samples, "occurrenceID", transform, materialSampleID = #paste(materialSampleID, collapse = "|"))
#keep only the first instance of each occurrenceID
#fish_samples<-fish_samples[!duplicated(fish_samples$occurrenceID),]

Format samples to schema

#change all empty columns from logical to character class
fish_samples[sapply(fish_samples, is.logical)] <- lapply(fish_samples[sapply(fish_samples, is.logical)],  as.character)
#Fix the eventIDs
fish_samples$eventID<-str_extract(fish_samples$eventID,"KANF\\d\\d\\d")
fish_samples$otherCatalogNumbers<-NULL # drop this for now - it will be replaced by fish_biorep below
# class(fish_samples[,which(sapply(fish_samples, is.logical))])<-"character"
# class(fish_samples$occurrenceID)
# class(fish_samples$basisofRecord)
# class(fish_samples$catalogNumber)<-"character"
# class(fish_samples$organismScope)
# class(fish_samples$eventID)
# class(fish_samples$scientificName) #eventually parse this into taxon categories?
# class(fish_samples$taxonRank) #using this
# class(fish_samples$individualCount)
# class(fish_samples$institutionID)
# make identifiedBy go firstname lastname
fish_samples$identifiedBy<-str_replace(fish_samples$identifiedBy, pattern="(\\w+), (.+)", replacement="\\2 \\1")
fish_samples$catalogNumber<-as.character(fish_samples$catalogNumber)

Format the biorepository info

colnames(fish_genetic)[5]<-"BiorepositoryID"
colnames(fish_genetic)[6]<-"tissueNotes"
colnames(fish_genetic)[2]<-"occurrenceID"
#use ddply to lump all materialSampleIDs into a single field, separated by a |
fish_biorep<-ddply(fish_genetic, "occurrenceID", transform, otherCatalogNumbers = paste(BiorepositoryID, collapse = "|"), tissueNotes = paste(tissueNotes, collapse="|"))
#keep only the first instance of each occurrenceID
fish_biorep<-fish_biorep[!duplicated(fish_biorep$otherCatalogNumbers),]
fish_biorep$otherCatalogNumbers<-as.character(fish_biorep$otherCatalogNumbers)

Join the event data onto the occurrence data

#first join the biorep numbers to this data
fish_samples<-left_join(fish_samples,fish_biorep[,c(2,6,7)],by="occurrenceID")
#now join samples and events
fish<-left_join(fish_samples,events,by="eventID")

Make a Map

#optionally make it from the points provided
#bbox<-make_bbox(lon=fish2$decimalLongitude,lat=fish2$decimalLatitude)
#by individual
fish2<-fish %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(count=n()) 
#by species
fish3 <- fish %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
fish4<-fish3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
fish6<-left_join(fish2,fish4)
fish_map<-ggmap(dmap) + geom_point(data = fish6, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=count, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Species Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank())
fish_map
ggsave(fish_map,filename="./output/fish_map.pdf")

Algae

Import

#edit eventIDs for capitalization
algae_samples<-read_excel("/Users/eric/google_drive/MarineGEO/algae/MarineGEOHI_bioassessment_master_KANA.xlsx", sheet="Sample")

Format samples to schema

#change all empty columns from logical to character class
algae_samples[sapply(algae_samples, is.logical)] <- lapply(algae_samples[sapply(algae_samples, is.logical)],  as.character)
# class(algae_samples$occurrenceID)
# class(algae_samples$catalogNumber)
# class(algae_samples$otherCatalogNumbers)
# class(algae_samples$organismScope)
# class(algae_samples$eventID)
# class(algae_samples$scientificName) #eventually parse this into taxon categories?
# class(algae_samples$taxonRank) # Melinda needs to populate this...
# class(algae_samples$identifiedBy)
# class(algae_samples$individualCount)
algae_samples$basisofRecord<-"specimen"
algae_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

algae<-left_join(algae_samples,events,by="eventID")

Make A Map

#by individual
algae2<-algae %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(count=n()) 
#by species
algae3 <- algae[-which(algae$scientificName=="?"),] %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
algae4<-algae3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
algae5<-left_join(algae2,algae4)
#algae5<-algae5[which(is.na(algae5$decimalLatitude)),]
#algae5<-algae5[-which(algae5$scientificName=="?"),]
algae5[4,4]<-1
algae5[11,4]<-2
extra<-algae5[33,]
algae5<-algae5[-33,] #remove outlier
algae_map<-ggmap(dmap) + geom_point(data = algae5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=count, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) + geom_point(data=extra, mapping=aes(x = decimalLongitude, y = decimalLatitude, size=30, color=30))
#add outlier back in as a red dot size=30
algae_map
ggsave(algae_map,filename="./output/algae_map.pdf")

Macroinvertebrates

Import

invert_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Inverts/BKANE_063017_FIMS.xlsx", sheet = "Specimen",skip=3)
#sponges will be loaded here, cleaned up, and then joined with the rest of the inverts
sponge_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Sponges/VICENTE_BIOBLITZ2017_SPONGEMETADATA_FIMS.xlsx", sheet = "Sheet1",skip=1)
#remove columns that don't appear in MarineGEO schema
invert_samples<-invert_samples[,-grep(pattern = "^X",x = names(invert_samples),perl=T)]
sponge_samples<-sponge_samples[,-grep(pattern = "^X",x = names(sponge_samples),perl=T)]
#remove records without occurrenceIDs (temp before final dataset)
invert_samples<-invert_samples[-which(is.na(invert_samples$scientificName)),]
sponge_samples<-sponge_samples[-which(is.na(sponge_samples$scientificName)),]
#change all empty columns from logical to character class
invert_samples[sapply(invert_samples, is.logical)] <- lapply(invert_samples[sapply(invert_samples, is.logical)],  as.character)
sponge_samples[sapply(sponge_samples, is.logical)] <- lapply(sponge_samples[sapply(sponge_samples, is.logical)],  as.character)
sponge_samples$phylum[which(is.na(sponge_samples$phylum))]<-"Porifera"
sponge_samples$eventID<-str_replace(sponge_samples$eventID,pattern="-", replacement="")
invert_samples<-full_join(invert_samples,sponge_samples)

Taxonomize

This code will populate taxonRank with the lowest known taxonomic category

invert_samples$taxonRank[which(!is.na(invert_samples$phylum))]<-"phylum"
invert_samples$taxonRank[which(!is.na(invert_samples$class))]<-"class"
invert_samples$taxonRank[which(!is.na(invert_samples$subclass))]<-"subclass"
invert_samples$taxonRank[which(!is.na(invert_samples$order))]<-"order"
invert_samples$taxonRank[which(!is.na(invert_samples$suborder))]<-"suborder"
invert_samples$taxonRank[which(!is.na(invert_samples$superfamily))]<-"superfamily"
invert_samples$taxonRank[which(!is.na(invert_samples$family))]<-"family"
invert_samples$taxonRank[which(!is.na(invert_samples$subfamily))]<-"subfamily"
invert_samples$taxonRank[which(!is.na(invert_samples$genus))]<-"genus"
invert_samples$taxonRank[which(!is.na(invert_samples$species))]<-"species"
invert_samples$taxonRank[grep("sp\\.",invert_samples$species)]<-"genus"

Format samples to schema

#change all empty columns from logical to character class moved this up
#invert_samples[sapply(invert_samples, is.logical)] <- #lapply(invert_samples[sapply(invert_samples, is.logical)],  as.character)
# class(invert_samples$occurrenceID)
# class(invert_samples$scientificName) #eventually parse this into taxon categories?
# class(invert_samples$taxonRank) #using this
invert_samples$basisOfRecord<-"specimen"
invert_samples$organismScope<-"organism"
#remove eventIDs that have two possibilities, assume it is the first one for now
invert_samples$eventID<-gsub(pattern="(\\w) or \\w",replacement="\\1",x= invert_samples$eventID,perl=T)
#fix arms eventIDs
invert_samples$eventID[grep(pattern="KANEO",invert_samples$eventID)]<-str_replace(string=invert_samples$eventID[grep(pattern="KANEO",invert_samples$eventID)],pattern="KANEO\\d(\\d\\d)", replacement="KANEO_2017_ARMS\\1")
invert_samples$identifiedBy<-"Paulay, Gustav" # for now. don't know if they kept this info
#assume that blank counts had 1 individual for now
invert_samples$individualCount[is.na(invert_samples$individualCount)]<-1
invert_samples$institutionID<-"FLMNH"

Join the event data onto the occurrence data

invert<-left_join(invert_samples,events,by="eventID")

Make A Map

#by individual
invert2<-invert %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
invert3 <- invert %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
invert4<-invert3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
invert5<-left_join(invert2,invert4)
invert_map<-ggmap(dmap) + geom_point(data = invert5[-c(length(invert5$richness)-1,length(invert5$richness)),], mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
invert_map
ggsave(invert_map,filename="./output/invert_map.pdf")

#create a vector of the eventIDs not finding a match in the events database
bad_eventIDs<-invert$eventID[which(is.na(invert$decimalLatitude))]

Make A Sponge Map

sponge<-invert[which(invert$phylum=="Porifera"),]
#by individual
sponge2<-sponge %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
sponge3 <- sponge %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
sponge4<-sponge3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
sponge5<-left_join(sponge2,sponge4)
sponge_map<-ggmap(dmap) + geom_point(data = sponge5[-c(61,62),], mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
sponge_map
ggsave(sponge_map,filename="./output/sponge_map.pdf")

Meiofauna

Import

#note meio data still need some cleaning, including importing some stations from inverts and fish, and fixing up eventIDs to have 3 digits instead of 2. There are 27 specimens that do not have station information because of this.
meio_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Meiofauna/Hawaii2017_meiofauna_MarineGEO.xlsx", sheet = "specimen data",skip=1)
#remove columns that don't appear in MarineGEO schema
meio_samples<-meio_samples[,-grep(pattern = "^X",x = names(meio_samples),perl=T)]
#add occurrence IDs to one investigators samples - this has been taken care of now
#meio_samples$occurrenceID[which(is.na(meio_samples$occurrenceID))]<-"UJ" 
#make occurrence IDs unique
#meio_samples$occurrenceID<-make.unique(meio_samples$occurrenceID, sep="_")

Format samples to schema

#change all empty columns from logical to character class
meio_samples[sapply(meio_samples, is.logical)] <- lapply(meio_samples[sapply(meio_samples, is.logical)],  as.character)
meio_samples$basisofRecord<-"specimen" #check with Frey that this is correct
meio_samples$institutionID<-"USNM"
# class(meio_samples$scientificName) #eventually parse this into taxon categories?
# class(meio_samples$taxonRank) #using this
# class(meio_samples$occurrenceID)
# class(meio_samples$catalogNumber)
# class(meio_samples$otherCatalogNumbers)
# class(meio_samples$organismScope)
# class(meio_samples$eventID)
# class(meio_samples$identifiedBy)
# class(meio_samples$individualCount)

Join the event data onto the occurrence data

meio<-left_join(meio_samples,meio_events,by="eventID")

Make A Map

#by individual
meio2<-meio %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
meio3 <- meio %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
meio4<-meio3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
meio5<-left_join(meio2,meio4)
meio_map<-ggmap(dmap) + geom_point(data = meio5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
meio_map
ggsave(meio_map,filename="./output/meio_map.pdf")

ARMS

Import

arms_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/ARMS/MarineGEOHI_bioassessment_master-ARMS.xlsx", sheet = "Sample")

Format samples to schema

#change all empty columns from logical to character class
arms_samples[sapply(arms_samples, is.logical)] <- lapply(arms_samples[sapply(arms_samples, is.logical)],  as.character)
# class(arms_samples$occurrenceID)
# class(arms_samples$basisofRecord)
# class(arms_samples$catalogNumber)
# class(arms_samples$otherCatalogNumbers)
# class(arms_samples$organismScope) #were there some slurries too?
# class(arms_samples$eventID)
# class(arms_samples$scientificName) #eventually parse this into taxon categories?
# class(arms_samples$taxonRank) #using this
# class(arms_samples$identifiedBy)
# class(arms_samples$individualCount)
# change NAs for individualCount to 1 for now
arms_samples$individualCount[which(is.na(arms_samples$individualCount))]<-1
arms_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

arms<-left_join(arms_samples,arms_events,by="eventID")

Make A Map

#by individual
arms2<-arms %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
arms3 <- arms %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n())
#richness
arms4<-arms3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
arms5<-left_join(arms2,arms4)
arms_map<-ggmap(dmap) + geom_point(data = arms5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Type Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
arms_map
ggsave(arms_map,filename="./output/arms_map.pdf")

Visual Transects

Import

trans_samples<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/bioassessment_KANV.xlsx", sheet = "Sample")
trans_organism_photos<-read_excel(path="/Users/eric/google_drive/MarineGEO/Transects/KANV_photo-vouchers_20170712.xlsx", sheet = "Sheet1")

Format, collapse and merge the media fields

Organism photos

trans_samples$associatedMedia<-NULL
Warning messages:
1: Unknown column 'identifiedBy' 
2: Unknown column 'identifiedBy' 

Format samples to schema

#change all empty columns from logical to character class
trans_samples[sapply(trans_samples, is.logical)] <- lapply(trans_samples[sapply(trans_samples, is.logical)],  as.character)
# class(trans_samples$occurrenceID)
# class(trans_samples$basisofRecord)
# class(trans_samples$catalogNumber)
# class(trans_samples$otherCatalogNumbers)
# class(trans_samples$organismScope)
# class(trans_samples$eventID)
# class(trans_samples$scientificName) #eventually parse this into taxon categories?
# class(trans_samples$taxonRank) #using this
# class(trans_samples$identifiedBy)
# class(trans_samples$individualCount)
trans_samples$institutionID<-"USNM"

Join the event data onto the occurrence data

trans<-left_join(trans_samples,trans_events,by="eventID")

Make A Map

#by individual
trans2<-trans %>% group_by(decimalLatitude, decimalLongitude) %>% summarize(individualCount=sum(individualCount,na.rm = T)) 
#by species
trans3 <- trans %>% group_by(scientificName, decimalLatitude, decimalLongitude) %>% summarize(count=n(), individualCount=sum(individualCount,na.rm=T))
#richness
trans4<-trans3 %>% group_by(decimalLatitude,decimalLongitude) %>% summarize(richness=n())
trans5<-left_join(trans2,trans4)
trans_map<-ggmap(dmap) + geom_point(data = trans5, mapping = aes(x = decimalLongitude, y = decimalLatitude, size=individualCount, color=richness)) + scale_color_gradient(low = "green", high="red") + guides(color=guide_colorbar(title="Species Richness",), size=guide_legend(title="Individual Count")) + theme(axis.title=element_blank()) 
trans_map
ggsave(trans_map,filename="./output/trans_map.pdf")

Final Database

Now to join everything into one monster database

WriteXLS(c(MarineGEOHI2,as.data.frame(events)),ExcelFileName = "./output/MarineGEOHI_data_1.1.xlsx",SheetNames=c("Events","Samples"))
Error in WriteXLS(c(MarineGEOHI2, as.data.frame(events)), ExcelFileName = "./output/MarineGEOHI_data_1.1.xlsx",  : 
  One or more of the objects named in 'x' is not a data frame or does not exist
LS0tCnRpdGxlOiAiTWFyaW5lR0VPIERhdGEgRm9ybWF0dGluZywgU3VtbWFyaXppbmcgYW5kIGpvaW5pbmciCmF1dGhvcjogIkVyaWMgRC4gQ3JhbmRhbGwiCmRhdGU6ICI1LzI5LzIwMTciCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFCikKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdnbWFwKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKZmlsZWRpcjwtIn4vZ29vZ2xlX2RyaXZlL01hcmluZUdFTyIKCmJib3g8LWMobGVmdD0tMTU3Ljg1LGJvdHRvbT0gMjEuMzgscmlnaHQ9LTE1Ny43NSwgdG9wPTIxLjU1KQpkbWFwIDwtIGdldF9tYXAobG9jYXRpb24gPSBiYm94LCBtYXB0eXBlID0gInNhdGVsbGl0ZSIsIHNvdXJjZSA9ICJnb29nbGUiKQoKIyB0byBkbzoKCiMgc3BsaXQgc2NpZW50aWZpYyBuYW1lIGludG8gZ2VudXMgYW5kIHNwZWNpZXMgd2hlcmUgYXBwcm9wcmlhdGUKIyBzcC4gY2hhbmdlcyBsb3dlc3Qga25vd24gdG8gZ2VudXMKIyBvcmdhbmlzbVJlbWFya3MgPT0gIkJpc2hvcCIgLSBjaGFuZ2UgaW5zdGl0dXRpb25JRCB0byAiQmlzaG9wIE11c2V1bSIKIyBvcmdhbmlzbVNjb3BlID0gYnVsayBsb3QgaWYgaW5kaXZpZHVhbENvdW50ID4gMQojIGFkZCBvbiBsb2NhdGlvbiBpbmZvIHNwZWNpZmljIHRvIEthbmVvaGUgQmF5CgpgYGAKIyBCdWlsZCBFdmVudHMgRGF0YWJhc2UKCiMjIEZpc2gKYGBge3IgRmlzaCBFdmVudHN9CgpmaXNoX2V2ZW50czwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL0Zpc2gvRklTSF9EQVRBXzIxSnVsMjAxNy54bHN4IixzaGVldD0iRXZlbnRzIikKCiMjIyBGb3JtYXQgZXZlbnRzIHRvIHNjaGVtYQoKI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCmZpc2hfZXZlbnRzW3NhcHBseShmaXNoX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShmaXNoX2V2ZW50c1tzYXBwbHkoZmlzaF9ldmVudHMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiNjaGFuZ2UgZXZlbnRJRCB0byBqdXN0IHRoZSBLQU5GIHZhbHVlCmZpc2hfZXZlbnRzJGV2ZW50SUQ8LXN0cl9leHRyYWN0KGZpc2hfZXZlbnRzJGV2ZW50SUQsIktBTkZcXGRcXGRcXGQiKQoKI3JvdW5kIHRoZSBsYXQvbG9uZ3MgdG8gZm91ciBkaWdpdHMgKH4gMTBtIHVuY2VydGFpbnR5KQpmaXNoX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMoZmlzaF9ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQpmaXNoX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlPC1yb3VuZChhcy5udW1lcmljKGZpc2hfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGUpLGRpZ2l0cyA9IDQpCgpmaXNoX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVyczwtYXMubnVtZXJpYyhmaXNoX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykgCgojIGNsYXNzKGZpc2hfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKQojIGNsYXNzKGZpc2hfZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzKQojIGNsYXNzKGZpc2hfZXZlbnRzJG1pbmltdW1EZXB0aEluTWV0ZXJzKQojIGNsYXNzKGZpc2hfZXZlbnRzJHJlY29yZGVkQnkpIAojIGNsYXNzKGZpc2hfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBEaWFuZSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhmaXNoX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI3JlbW92ZSBjYXJyaWFnZSByZXR1cm5zIGZyb20gR2VvbW9ycGhvbG9naWNhbCBab25lCmZpc2hfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZTwtc3RyX3JlcGxhY2VfYWxsKGZpc2hfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZSxwYXR0ZXJuPSJcclxuIixyZXBsYWNlbWVudCA9ICIiKQpmaXNoX2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlPC1zdHJfcmVwbGFjZV9hbGwoZmlzaF9ldmVudHMkaGFiaXRhdFN1YnN0cmF0ZSxwYXR0ZXJuPSJcclxuIixyZXBsYWNlbWVudCA9ICIiKQoKZmlzaF9ldmVudHMkeWVhcjwtYXMubnVtZXJpYyhmaXNoX2V2ZW50cyR5ZWFyKQpmaXNoX2V2ZW50cyRtb250aDwtbWF0Y2goZmlzaF9ldmVudHMkbW9udGgsbW9udGguYWJiKQpmaXNoX2V2ZW50cyRkYXk8LWFzLm51bWVyaWMoZmlzaF9ldmVudHMkZGF5KQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGZpc2hfZXZlbnRzJGV2ZW50UmVtYXJrcykKIyBjbGFzcyhmaXNoX2V2ZW50cyRsb2NhbGl0eSkKIyBjbGFzcyhmaXNoX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoZmlzaF9ldmVudHMkdmVyYmF0aW1Db29yZGluYXRlcykKIyBjbGFzcyhmaXNoX2V2ZW50cyRldmVudE1lZGlhKQoKI3JlbW92ZSBlbmRpbmcgdGltZXMgZnJvbSBldmVudFRpbWUgZmllbGQKZmlzaF9ldmVudHMkZXZlbnRUaW1lPC1zdHJfZXh0cmFjdChzdHJpbmc9ZmlzaF9ldmVudHMkZXZlbnRUaW1lLHBhdHRlcm49Il5cXGRcXGQ6XFxkXFxkIikKCmBgYAoKIyMgQWxnYWUKCmBgYHtyIEFsZ2FlIEV2ZW50c30KCmFsZ2FlX2V2ZW50czwtcmVhZF9leGNlbCgiL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9hbGdhZS9NYXJpbmVHRU9ISV9iaW9hc3Nlc3NtZW50X21hc3Rlcl9LQU5BLnhsc3giLCBzaGVldD0iU3RhdGlvbiIpCgojIyMgRm9ybWF0IGV2ZW50cyB0byBzY2hlbWEKCiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwphbGdhZV9ldmVudHNbc2FwcGx5KGFsZ2FlX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShhbGdhZV9ldmVudHNbc2FwcGx5KGFsZ2FlX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCiNyb3VuZCB0byA0IGRlY2ltYWwgZGlnaXRzICh+MTBtIHVuY2VydGFpbnR5KSBhbmQgbWVha2Ugc3VyZSBsb25naXR1ZGUgaXMgbmVnYXRpdmUKCmFsZ2FlX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMoYWxnYWVfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKYWxnYWVfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKGFsZ2FlX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGV2ZW50SUQpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKSAjZ29vZAojIGNsYXNzKGFsZ2FlX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykgI2dvb2QKIyBjbGFzcyhhbGdhZV9ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpICNzb21lIG1pc3NpbmcuIGFzayBNZWxpbmRhIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGFsZ2FlX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykjc29tZSBtaXNzaW5nLiBhc2sgTWVsaW5kYSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhhbGdhZV9ldmVudHMkcmVjb3JkZWRCeSkgI3NvbWUgbWlzc2luZy4gYXNrIE1lbGluZGEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MoYWxnYWVfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBNZWxpbmRhIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGFsZ2FlX2V2ZW50cyRgaGFiaXRhdEJpb3RpY2ApCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGBoYWJpdGF0R2VvbW9ycGhvbG9naWNhbFpvbmVgKQojIGNsYXNzKGFsZ2FlX2V2ZW50cyRgaGFiaXRhdFN1YnN0cmF0ZWApCgoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGFsZ2FlX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGFsZ2FlX2V2ZW50cyRldmVudFJlbWFya3MpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJHZlcmJhdGltQ29vcmRpbmF0ZXMpCiMgY2xhc3MoYWxnYWVfZXZlbnRzJGV2ZW50TWVkaWEpCgojZm9ybWF0IHRpbWUgY29ycmVjdGx5CmFsZ2FlX2V2ZW50cyRldmVudFRpbWU8LWFzLmNoYXJhY3RlcihwYXJzZV9kYXRlX3RpbWUoYWxnYWVfZXZlbnRzJGV2ZW50VGltZSwgb3JkZXJzPSJ5bWRITVMiLCB0ej0iSFNUIiksZm9ybWF0PSIlSDolTSIpCgoKYGBgCgojIyBNYWNyb2ludmVydGVicmF0ZXMKCmBgYHtyIEludmVydCBFdmVudHN9CgppbnZlcnRfZXZlbnRzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vSW52ZXJ0cy9CS0FORV8wNjMwMTdfRklNUy54bHN4Iiwgc2hlZXQgPSAiU3RhdGlvbiIsIHNraXA9MikKCgoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCiMgTm90ZTogaW52ZXJ0IGV2ZW50IGRhdGEgbmVlZCBhIGxvdCBvZiBjbGVhbmluZywgaW5jbHVkaW5nIGltcG9ydGluZyBzdGF0aW9ucyBmcm9tIHRoZSBhbGdhZSBhbmQgbWVpb2ZhdW5hIHRlYW0sIGFuZCBtYWtpbmcgbmV3IHN0YXRpb25zIHdpdGggIkEiIG9yICJCIiBhcHBlbmRlZC4gQ3VycmVudGx5IDgzOSBzYW1wbGVzIGRvIG5vdCBoYXZlIHN0YXRpb24gaW5mb3JtYXRpb24gYmVjYXVzZSBvZiB0aGlzLgoKIyByZW1vdmUgZXZlbnQgZmllbGRzIHRoYXQgZG9uJ3QgYXBwZWFyIGluIHRoZSBzY2hlbWEKaW52ZXJ0X2V2ZW50czwtaW52ZXJ0X2V2ZW50c1ssLWdyZXAocGF0dGVybiA9ICJeWCIseCA9IG5hbWVzKGludmVydF9ldmVudHMpLHBlcmw9VCldCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKaW52ZXJ0X2V2ZW50c1tzYXBwbHkoaW52ZXJ0X2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseShpbnZlcnRfZXZlbnRzW3NhcHBseShpbnZlcnRfZXZlbnRzLCBpcy5sb2dpY2FsKV0sICBhcy5jaGFyYWN0ZXIpCgojcm91bmQgdG8gNCBkZWNpbWFsIGRpZ2l0cyAofjEwbSB1bmNlcnRhaW50eSkgYW5kIG1lYWtlIHN1cmUgbG9uZ2l0dWRlIGlzIG5lZ2F0aXZlCmludmVydF9ldmVudHMkZGVjaW1hbExhdGl0dWRlPC1yb3VuZChhcy5udW1lcmljKGludmVydF9ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQppbnZlcnRfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKGludmVydF9ldmVudHMkZGVjaW1hbExvbmdpdHVkZSksZGlnaXRzID0gNCkpKi0xCgppbnZlcnRfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sPC0iR1BTIgppbnZlcnRfZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMDAKCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRtYXhpbXVtRGVwdGhJbk1ldGVycykgI3NvbWUgbWlzc2luZy4gYXNrIEpvaG4gdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykjc29tZSBtaXNzaW5nLiBhc2sgSm9obiB0byBmaWxsIHRoaXMgaW4KCiNGb3JtYXQgdGhlIGRhdGUgcHJvcGVybHksIGdldCByaWQgb2YgdGhlICJyYXciIGZpZWxkCmludmVydF9ldmVudHMkZGF5PC1kYXkoaW52ZXJ0X2V2ZW50cyRldmVudERhdGUpCmludmVydF9ldmVudHMkbW9udGg8LW1vbnRoKGludmVydF9ldmVudHMkZXZlbnREYXRlKQppbnZlcnRfZXZlbnRzJHllYXI8LXllYXIoaW52ZXJ0X2V2ZW50cyRldmVudERhdGUpCmludmVydF9ldmVudHMkZXZlbnREYXRlPC1OVUxMCgojIGNsYXNzKGludmVydF9ldmVudHMkcmVjb3JkZWRCeSkgI2dvb2QKIyBjbGFzcyhpbnZlcnRfZXZlbnRzJHNhbXBsaW5nUHJvdG9jb2wpICNzb21lIG1pc3NpbmcuIGFzayBKb2huIHRvIGZpbGwgdGhpcyBpbgojIGNsYXNzKGludmVydF9ldmVudHMkaGFiaXRhdEdlb21vcnBob2xvZ2ljYWxab25lKSAjc29tZSBtaXNzaW5nLiBhc2sgSm9obiB0byBmaWxsIHRoaXMgaW4uICN0aGlzIG5lZWRzIHRvIGJlIGFsaWduZWQgd2l0aCB0aGUgc2NoZW1hCiMgY2xhc3MoaW52ZXJ0X2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlKSAjIHNvbWUgbWlzc2luZy4gYXNrIEpvaG4gdG8gZmlsbCB0aGlzIGluLiAjdGhpcyBuZWVkcyB0byBiZSBhbGlnbmVkIHdpdGggdGhlIHNjaGVtYQoKCiNSZWNvbW1lbmRlZCBmaWVsZHMKIyBjbGFzcyhpbnZlcnRfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGludmVydF9ldmVudHMkZXZlbnRSZW1hcmtzKQoKYGBgCgojIyBNZWlvZmF1bmEKCmBgYHtyIE1laW8gRXZlbnRzfQoKbWVpb19ldmVudHM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9NZWlvZmF1bmEvSGF3YWlpMjAxN19tZWlvZmF1bmFfTWFyaW5lR0VPLnhsc3giLCBzaGVldCA9ICJzdGF0aW9uIGRhdGEiLCBza2lwPTEpCgojcmVtb3ZlIGNvbHVtbnMgdGhhdCBkb24ndCBhcHBlYXIgaW4gTWFyaW5lR0VPIHNjaGVtYQptZWlvX2V2ZW50czwtbWVpb19ldmVudHNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhtZWlvX2V2ZW50cykscGVybD1UKV0KCiMjIyBGb3JtYXQgZXZlbnRzIHRvIHNjaGVtYQoKI01pc3Npbmcgc3RhdGlvbiBLQU5NMDg3ISEhCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKbWVpb19ldmVudHNbc2FwcGx5KG1laW9fZXZlbnRzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KG1laW9fZXZlbnRzW3NhcHBseShtZWlvX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKI3JvdW5kIHRvIDQgZGVjaW1hbCBkaWdpdHMgKH4xMG0gdW5jZXJ0YWludHkpIGFuZCBtZWFrZSBzdXJlIGxvbmdpdHVkZSBpcyBuZWdhdGl2ZQptZWlvX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWMobWVpb19ldmVudHMkZGVjaW1hbExhdGl0dWRlKSxkaWdpdHMgPSA0KQptZWlvX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlPC1hYnMocm91bmQoYXMubnVtZXJpYyhtZWlvX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCm1laW9fZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMDAKbWVpb19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnM8LWFzLm51bWVyaWMobWVpb19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCm1laW9fZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzPC1hcy5udW1lcmljKG1laW9fZXZlbnRzJG1heGltdW1EZXB0aEluTWV0ZXJzKQoKIyBjbGFzcyhtZWlvX2V2ZW50cyRtYXhpbXVtRGVwdGhJbk1ldGVycykKIyBjbGFzcyhtZWlvX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVycykKIyBjbGFzcyhtZWlvX2V2ZW50cyRyZWNvcmRlZEJ5KSAjYXNrIEZyZXlhIHRvIGZvbGxvdyBmb3JtYXQgLSBhZGQgbGFzdCBuYW1lcywgYW5kIHBpcGVzIGJldHdlZW4gbmFtZXMKIyBjbGFzcyhtZWlvX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKSAjc29tZSBtaXNzaW5nLiBhc2sgRnJleWEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MobWVpb19ldmVudHMkaGFiaXRhdEdlb21vcnBob2xvZ2ljYWxab25lKSAjc29tZSBtaXNzaW5nLiBhc2sgRnJleWEgdG8gZmlsbCB0aGlzIGluCiMgY2xhc3MobWVpb19ldmVudHMkaGFiaXRhdFN1YnN0cmF0ZSkgIyBzb21lIG1pc3NpbmcuIGFzayBGcmV5YSB0byBmaWxsIHRoaXMgaW4KIyBjbGFzcyhtZWlvX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKG1laW9fZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKG1laW9fZXZlbnRzJGV2ZW50UmVtYXJrcykKCm1laW9fZXZlbnRzJGRheTwtZGF5KG1laW9fZXZlbnRzJGV2ZW50RGF0ZSkKbWVpb19ldmVudHMkbW9udGg8LW1vbnRoKG1laW9fZXZlbnRzJGV2ZW50RGF0ZSkKbWVpb19ldmVudHMkeWVhcjwteWVhcihtZWlvX2V2ZW50cyRldmVudERhdGUpCm1laW9fZXZlbnRzJGV2ZW50RGF0ZTwtTlVMTAoKI2Zvcm1hdCB0aGUgJF4jJiogdGltZSBjb3JyZWN0bHkKbWVpb19ldmVudHMkZXZlbnRUaW1lPC1mb3JtYXQoLlBPU0lYY3QoODY0MDAqYXMubnVtZXJpYyhtZWlvX2V2ZW50cyRldmVudFRpbWUpLCAiVVRDIiksICIlSDolTSIpCiNtZWlvX2V2ZW50cyRldmVudFRpbWU8LWFzLmNoYXJhY3RlcihwYXJzZV9kYXRlX3RpbWUobWVpb19ldmVudHMkZXZlbnRUaW1lLCBvcmRlcnM9InltZEhNUyIsIHR6PSJIU1QiKSxmb3JtYXQ9IiVIOiVNIikKCm1laW9fZXZlbnRzJGV2ZW50TWVkaWE8LSJOIgoKYGBgCgojIyBBUk1TCgpgYGB7ciBBUk1TIGV2ZW50c30KYXJtc19ldmVudHM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9BUk1TL01hcmluZUdFT0hJX2Jpb2Fzc2Vzc21lbnRfbWFzdGVyLUFSTVMueGxzeCIsIHNoZWV0ID0gIlN0YXRpb24iKQoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKYXJtc19ldmVudHNbc2FwcGx5KGFybXNfZXZlbnRzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KGFybXNfZXZlbnRzW3NhcHBseShhcm1zX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCiNyb3VuZCB0byA0IGRlY2ltYWwgZGlnaXRzICh+MTBtIHVuY2VydGFpbnR5KSBhbmQgbWVha2Ugc3VyZSBsb25naXR1ZGUgaXMgbmVnYXRpdmUKYXJtc19ldmVudHMkZGVjaW1hbExhdGl0dWRlPC1yb3VuZChhcy5udW1lcmljKGFybXNfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKYXJtc19ldmVudHMkZGVjaW1hbExvbmdpdHVkZTwtYWJzKHJvdW5kKGFzLm51bWVyaWMoYXJtc19ldmVudHMkZGVjaW1hbExvbmdpdHVkZSksZGlnaXRzID0gNCkpKi0xCmFybXNfZXZlbnRzJGNvb3JkaW5hdGVVbmNlcnRhaW50eUluTWV0ZXJzPC0xMAoKYXJtc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnM8LWFzLm51bWVyaWMoYXJtc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCgojIGNsYXNzKGFybXNfZXZlbnRzJGdlb1JlZmVyZW5jZVByb3RvY29sKQojIGNsYXNzKGFybXNfZXZlbnRzJGV2ZW50SUQpCiMgY2xhc3MoYXJtc19ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpCiMgY2xhc3MoYXJtc19ldmVudHMkcmVjb3JkZWRCeSkgI2FzayBMYWV0aXRpYSB0byBmb2xsb3cgbmFtZSBmb3JtYXQKIyBjbGFzcyhhcm1zX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKQojIGNsYXNzKGFybXNfZXZlbnRzJGhhYml0YXRHZW9tb3JwaG9sb2dpY2FsWm9uZSkKIyBjbGFzcyhhcm1zX2V2ZW50cyRoYWJpdGF0U3Vic3RyYXRlKSAKIyBjbGFzcyhhcm1zX2V2ZW50cyRoYWJpdGF0QmlvdGljKQoKI1JlY29tbWVuZGVkIGZpZWxkcwojIGNsYXNzKGFybXNfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKGFybXNfZXZlbnRzJHllYXIpCiMgY2xhc3MoYXJtc19ldmVudHMkbW9udGgpCiMgY2xhc3MoYXJtc19ldmVudHMkZGF5KQoKYXJtc19ldmVudHMkZXZlbnRNZWRpYTwtIlkiICNzdGlsbCBuZWVkIHRvIGdldCB0aGVzZSBmcm9tIExhZXRpdGlhCgpgYGAKCiMjIFZpc3VhbCBUcmFuc2VjdHMKCmBgYHtyIFRyYW5zZWN0IEV2ZW50c30KdHJhbnNfZXZlbnRzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vVHJhbnNlY3RzL2Jpb2Fzc2Vzc21lbnRfS0FOVi54bHN4Iiwgc2hlZXQgPSAiU3RhdGlvbiIpCgp0cmFuc19ldmVudF9waG90b3M8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9UcmFuc2VjdHMvS0FOVl9iZW50aGljLXBob3Rvc19maWxlbmFtZXNfMjAxNzA3MTEueGxzeCIsIHNoZWV0ID0gIlNoZWV0MSIpCgojIGV2ZW50IHBob3RvcwojcG9wIG9mZiB0aGUgZXZlbnRJRCBpbnRvIGl0cyBvd24gZmllbGQKdHJhbnNfZXZlbnRfcGhvdG9zJGV2ZW50SUQ8LXN1YihwYXR0ZXJuPSIoS0FOVlxcZFxcZFxcZClfLisiLHJlcGxhY2VtZW50ID0gIlxcMSIsIHRyYW5zX2V2ZW50X3Bob3RvcyRldmVudE1lZGlhLCBwZXJsPVQpCgojdXNlIGRkcGx5IHRvIGx1bXAgYWxsIGV2ZW50TWVkaWEgaW50byBhIHNpbmdsZSBmaWVsZCwgc2VwYXJhdGVkIGJ5IGEgfAp0cmFuc19ldmVudE1lZGlhPC1kZHBseSh0cmFuc19ldmVudF9waG90b3MsICJldmVudElEIiwgdHJhbnNmb3JtLCBldmVudE1lZGlhID0gcGFzdGUoZXZlbnRNZWRpYSwgY29sbGFwc2UgPSAifCIpKQoKI2tlZXAgb25seSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgZWFjaCBvY2N1cnJlbmNlSUQKdHJhbnNfZXZlbnRNZWRpYTwtdHJhbnNfZXZlbnRNZWRpYVshZHVwbGljYXRlZCh0cmFuc19ldmVudE1lZGlhJGV2ZW50SUQpLF0KCiNkZWxldGUgb3JpZ2luYWwgZXZlbnRNZWRpYSBjb2x1bW4gYW5kIGpvaW4gb24gdGhlIG5ldyBvbmUKdHJhbnNfZXZlbnRzJGV2ZW50TWVkaWE8LU5VTEwKdHJhbnNfZXZlbnRzPC1sZWZ0X2pvaW4odHJhbnNfZXZlbnRzLCB0cmFuc19ldmVudE1lZGlhLCBieT0iZXZlbnRJRCIpCgoKIyMjIEZvcm1hdCBldmVudHMgdG8gc2NoZW1hCiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwp0cmFuc19ldmVudHNbc2FwcGx5KHRyYW5zX2V2ZW50cywgaXMubG9naWNhbCldIDwtIGxhcHBseSh0cmFuc19ldmVudHNbc2FwcGx5KHRyYW5zX2V2ZW50cywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQojcm91bmQgdG8gNCBkZWNpbWFsIGRpZ2l0cyAofjEwbSB1bmNlcnRhaW50eSkgYW5kIG1lYWtlIHN1cmUgbG9uZ2l0dWRlIGlzIG5lZ2F0aXZlCnRyYW5zX2V2ZW50cyRkZWNpbWFsTGF0aXR1ZGU8LXJvdW5kKGFzLm51bWVyaWModHJhbnNfZXZlbnRzJGRlY2ltYWxMYXRpdHVkZSksZGlnaXRzID0gNCkKdHJhbnNfZXZlbnRzJGRlY2ltYWxMb25naXR1ZGU8LWFicyhyb3VuZChhcy5udW1lcmljKHRyYW5zX2V2ZW50cyRkZWNpbWFsTG9uZ2l0dWRlKSxkaWdpdHMgPSA0KSkqLTEKCnRyYW5zX2V2ZW50cyRtaW5pbXVtRGVwdGhJbk1ldGVyczwtYXMubnVtZXJpYyh0cmFuc19ldmVudHMkbWluaW11bURlcHRoSW5NZXRlcnMpCgojIGNsYXNzKHRyYW5zX2V2ZW50cyRldmVudElEKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRjb29yZGluYXRlVW5jZXJ0YWludHlJbk1ldGVycykKIyBjbGFzcyh0cmFuc19ldmVudHMkbWF4aW11bURlcHRoSW5NZXRlcnMpCiMgY2xhc3ModHJhbnNfZXZlbnRzJHJlY29yZGVkQnkpIAojIGNsYXNzKHRyYW5zX2V2ZW50cyRzYW1wbGluZ1Byb3RvY29sKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRoYWJpdGF0R2VvbW9ycGhvbG9naWNhbFpvbmUpCiMgY2xhc3ModHJhbnNfZXZlbnRzJGhhYml0YXRTdWJzdHJhdGUpCiMgY2xhc3ModHJhbnNfZXZlbnRzJGhhYml0YXRCaW90aWMpCgojUmVjb21tZW5kZWQgZmllbGRzCiMgY2xhc3ModHJhbnNfZXZlbnRzJGxvY2FsaXR5KQojIGNsYXNzKHRyYW5zX2V2ZW50cyR5ZWFyKQojIGNsYXNzKHRyYW5zX2V2ZW50cyRtb250aCkKIyBjbGFzcyh0cmFuc19ldmVudHMkZGF5KQoKdHJhbnNfZXZlbnRzJGV2ZW50TWVkaWE8LSJZIgp0cmFuc19ldmVudHMkZXZlbnRUaW1lPC1hcy5jaGFyYWN0ZXIocGFyc2VfZGF0ZV90aW1lKHRyYW5zX2V2ZW50cyRldmVudFRpbWUsIG9yZGVycz0ieW1kSE1TIiwgdHo9IkhTVCIpLGZvcm1hdD0iJUg6JU0iKQoKYGBgCgojIyBKb2luIEV2ZW50cwoKYGBge3IgSm9pbiBFdmVudHN9CmV2ZW50czwtZnVsbF9qb2luKGZpc2hfZXZlbnRzLGFsZ2FlX2V2ZW50cykKZXZlbnRzPC1mdWxsX2pvaW4oZXZlbnRzLGludmVydF9ldmVudHMpCmV2ZW50czwtZnVsbF9qb2luKGV2ZW50cyxtZWlvX2V2ZW50cykKZXZlbnRzPC1mdWxsX2pvaW4oZXZlbnRzLGFybXNfZXZlbnRzKQpldmVudHM8LWZ1bGxfam9pbihldmVudHMsdHJhbnNfZXZlbnRzKQoKCgpgYGAKIyBCdWlsZCBzYW1wbGUgZGF0YWJhc2VzCgojIyBGaXNoCgojIyMgSW1wb3J0CmBgYHtyIEZpc2hfaW1wb3J0fQojIEZpcnN0IGdvIHRocm91Z2ggYW5kIG1ha2Ugc3VyZSBhbGwgc3RhdGlvbnMgaGF2ZSBMYXQvTG9uZ3MsIG9yIGFzIG1hbnkgYXMgcG9zc2libGUuIERlbGV0ZSBzZWNvbmRhcnkgbGF0L2xvbmdzCiNyZWFkIGluIHRoZSBzYW1wbGUgZGF0YSwgc2tpcHBpbmcgZmlyc3QgMyBsaW5lcyBvZiBvdGhlciBoZWFkZXJzLiBGb3JtYXQgYWxsIHRpbWVzIGFzIGhoOm1tIGluIEV4Y2VsLCBwYXN0ZSBpbnRvIHRleHR3cmFuZ2xlciBpZiB0aGV5IG5lZWQgaG9tb2dlbml6YXRpb24gKGkuZS4gbXVsdGlwbGUgZm9ybWF0cyBvZiB0aW1lcykKCmZpc2hfc2FtcGxlczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL0Zpc2gvRklTSF9EQVRBXzIxSnVsMjAxNy54bHN4IixzaGVldD0iU2FtcGxlcyIpCgpmaXNoX2dlbmV0aWM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9GaXNoL0ZJU0hfREFUQV8yMUp1bDIwMTcueGxzeCIsc2hlZXQ9IkdlbmV0aWMgc2FtcGxlcyIpCiN0aGVzZSBjb21tYW5kcyBhcHBseSB0byB0aGUgb3JpZ2luYWwgZmlzaC1ncm91cCB0ZW1wbGF0ZQojcmVtb3ZlIGNvbHVtbnMgd2l0aG91dCBtYXBwZWQgRHdDIHRlcm1zIG1hcHBlZAojZmlzaF9zYW1wbGVzPC1maXNoX3NhbXBsZXNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhmaXNoX3NhbXBsZXMpLHBlcmw9VCldCiNmaXNoX2V2ZW50czwtZmlzaF9ldmVudHNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhmaXNoX2V2ZW50cykscGVybD1UKV0KCiNyZW1vdmUgcmVjb3JkcyB3aXRob3V0IG9jY3VycmVuY2VJRHMgKHRlbXAgYmVmb3JlIGZpbmFsIGRhdGFzZXQpCiNmaXNoX3NhbXBsZXM8LWZpc2hfc2FtcGxlc1std2hpY2goaXMubmEoZmlzaF9zYW1wbGVzJG9jY3VycmVuY2VJRCkpLF0KI3RyYW5zbGF0ZSBmaWVsZElEcyB0byBldmVudElEcwojZmlzaF9zYW1wbGVzJGV2ZW50SUQ8LWdzdWIoIkxSUCAxNy0iLCJLQU5GMCIsZmlzaF9zYW1wbGVzJGV2ZW50SUQpCiN1c2UgZGRwbHkgdG8gbHVtcCBhbGwgbWF0ZXJpYWxTYW1wbGVJRHMgaW50byBhIHNpbmdsZSBmaWVsZCwgc2VwYXJhdGVkIGJ5IGEgfAojZmlzaF9zYW1wbGVzPC1kZHBseShmaXNoX3NhbXBsZXMsICJvY2N1cnJlbmNlSUQiLCB0cmFuc2Zvcm0sIG1hdGVyaWFsU2FtcGxlSUQgPSAjcGFzdGUobWF0ZXJpYWxTYW1wbGVJRCwgY29sbGFwc2UgPSAifCIpKQoja2VlcCBvbmx5IHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBlYWNoIG9jY3VycmVuY2VJRAojZmlzaF9zYW1wbGVzPC1maXNoX3NhbXBsZXNbIWR1cGxpY2F0ZWQoZmlzaF9zYW1wbGVzJG9jY3VycmVuY2VJRCksXQpgYGAKCgojIyMgRm9ybWF0IHNhbXBsZXMgdG8gc2NoZW1hCgpgYGB7ciBmb3JtYXQgZmlzaCBzYW1wbGVzfQojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKZmlzaF9zYW1wbGVzW3NhcHBseShmaXNoX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkoZmlzaF9zYW1wbGVzW3NhcHBseShmaXNoX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiNGaXggdGhlIGV2ZW50SURzCmZpc2hfc2FtcGxlcyRldmVudElEPC1zdHJfZXh0cmFjdChmaXNoX3NhbXBsZXMkZXZlbnRJRCwiS0FORlxcZFxcZFxcZCIpCgoKZmlzaF9zYW1wbGVzJG90aGVyQ2F0YWxvZ051bWJlcnM8LU5VTEwgIyBkcm9wIHRoaXMgZm9yIG5vdyAtIGl0IHdpbGwgYmUgcmVwbGFjZWQgYnkgZmlzaF9iaW9yZXAgYmVsb3cKCiMgY2xhc3MoZmlzaF9zYW1wbGVzWyx3aGljaChzYXBwbHkoZmlzaF9zYW1wbGVzLCBpcy5sb2dpY2FsKSldKTwtImNoYXJhY3RlciIKIyBjbGFzcyhmaXNoX3NhbXBsZXMkb2NjdXJyZW5jZUlEKQojIGNsYXNzKGZpc2hfc2FtcGxlcyRiYXNpc29mUmVjb3JkKQojIGNsYXNzKGZpc2hfc2FtcGxlcyRjYXRhbG9nTnVtYmVyKTwtImNoYXJhY3RlciIKIyBjbGFzcyhmaXNoX3NhbXBsZXMkb3JnYW5pc21TY29wZSkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkZXZlbnRJRCkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpICNldmVudHVhbGx5IHBhcnNlIHRoaXMgaW50byB0YXhvbiBjYXRlZ29yaWVzPwojIGNsYXNzKGZpc2hfc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCiMgY2xhc3MoZmlzaF9zYW1wbGVzJGluZGl2aWR1YWxDb3VudCkKIyBjbGFzcyhmaXNoX3NhbXBsZXMkaW5zdGl0dXRpb25JRCkKCiMgbWFrZSBpZGVudGlmaWVkQnkgZ28gZmlyc3RuYW1lIGxhc3RuYW1lCmZpc2hfc2FtcGxlcyRpZGVudGlmaWVkQnk8LXN0cl9yZXBsYWNlKGZpc2hfc2FtcGxlcyRpZGVudGlmaWVkQnksIHBhdHRlcm49IihcXHcrKSwgKC4rKSIsIHJlcGxhY2VtZW50PSJcXDIgXFwxIikKCmZpc2hfc2FtcGxlcyRjYXRhbG9nTnVtYmVyPC1hcy5jaGFyYWN0ZXIoZmlzaF9zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCgpgYGAKCiMjIyBGb3JtYXQgdGhlIGJpb3JlcG9zaXRvcnkgaW5mbwpgYGB7ciBmaXNoIGJpb3JlcG9zaXRvcnl9CmNvbG5hbWVzKGZpc2hfZ2VuZXRpYylbNV08LSJCaW9yZXBvc2l0b3J5SUQiCmNvbG5hbWVzKGZpc2hfZ2VuZXRpYylbNl08LSJ0aXNzdWVOb3RlcyIKY29sbmFtZXMoZmlzaF9nZW5ldGljKVsyXTwtIm9jY3VycmVuY2VJRCIKI3VzZSBkZHBseSB0byBsdW1wIGFsbCBtYXRlcmlhbFNhbXBsZUlEcyBpbnRvIGEgc2luZ2xlIGZpZWxkLCBzZXBhcmF0ZWQgYnkgYSB8CmZpc2hfYmlvcmVwPC1kZHBseShmaXNoX2dlbmV0aWMsICJvY2N1cnJlbmNlSUQiLCB0cmFuc2Zvcm0sIG90aGVyQ2F0YWxvZ051bWJlcnMgPSBwYXN0ZShCaW9yZXBvc2l0b3J5SUQsIGNvbGxhcHNlID0gInwiKSwgdGlzc3VlTm90ZXMgPSBwYXN0ZSh0aXNzdWVOb3RlcywgY29sbGFwc2U9InwiKSkKI2tlZXAgb25seSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgZWFjaCBvY2N1cnJlbmNlSUQKZmlzaF9iaW9yZXA8LWZpc2hfYmlvcmVwWyFkdXBsaWNhdGVkKGZpc2hfYmlvcmVwJG90aGVyQ2F0YWxvZ051bWJlcnMpLF0KZmlzaF9iaW9yZXAkb3RoZXJDYXRhbG9nTnVtYmVyczwtYXMuY2hhcmFjdGVyKGZpc2hfYmlvcmVwJG90aGVyQ2F0YWxvZ051bWJlcnMpCmBgYAoKIyMjIEpvaW4gdGhlIGV2ZW50IGRhdGEgb250byB0aGUgb2NjdXJyZW5jZSBkYXRhCgpgYGB7ciBmaXNoIGpvaW59CgojZmlyc3Qgam9pbiB0aGUgYmlvcmVwIG51bWJlcnMgdG8gdGhpcyBkYXRhCmZpc2hfc2FtcGxlczwtbGVmdF9qb2luKGZpc2hfc2FtcGxlcyxmaXNoX2Jpb3JlcFssYygyLDYsNyldLGJ5PSJvY2N1cnJlbmNlSUQiKQojbm93IGpvaW4gc2FtcGxlcyBhbmQgZXZlbnRzCmZpc2g8LWxlZnRfam9pbihmaXNoX3NhbXBsZXMsZXZlbnRzLGJ5PSJldmVudElEIikKCgpgYGAKCiMjIyBNYWtlIGEgTWFwCgpgYGB7ciBmaXNoIG1hcHN9CiNvcHRpb25hbGx5IG1ha2UgaXQgZnJvbSB0aGUgcG9pbnRzIHByb3ZpZGVkCiNiYm94PC1tYWtlX2Jib3gobG9uPWZpc2gyJGRlY2ltYWxMb25naXR1ZGUsbGF0PWZpc2gyJGRlY2ltYWxMYXRpdHVkZSkKI2J5IGluZGl2aWR1YWwKZmlzaDI8LWZpc2ggJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpIAoKI2J5IHNwZWNpZXMKZmlzaDMgPC0gZmlzaCAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKZmlzaDQ8LWZpc2gzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgpmaXNoNjwtbGVmdF9qb2luKGZpc2gyLGZpc2g0KQoKCmZpc2hfbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IGZpc2g2LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWNvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlNwZWNpZXMgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpCgpmaXNoX21hcAoKCmdnc2F2ZShmaXNoX21hcCxmaWxlbmFtZT0iLi9vdXRwdXQvZmlzaF9tYXAucGRmIikKCmBgYAoKCiMjIEFsZ2FlCgojIyMgSW1wb3J0CmBgYHtyIEFsZ2FlIGltcG9ydH0KI2VkaXQgZXZlbnRJRHMgZm9yIGNhcGl0YWxpemF0aW9uCgphbGdhZV9zYW1wbGVzPC1yZWFkX2V4Y2VsKCIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL2FsZ2FlL01hcmluZUdFT0hJX2Jpb2Fzc2Vzc21lbnRfbWFzdGVyX0tBTkEueGxzeCIsIHNoZWV0PSJTYW1wbGUiKQoKYGBgCgojIyMgRm9ybWF0IHNhbXBsZXMgdG8gc2NoZW1hCgpgYGB7ciBmb3JtYXQgYWxnYWUgc2FtcGxlc30KI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCmFsZ2FlX3NhbXBsZXNbc2FwcGx5KGFsZ2FlX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSA8LSBsYXBwbHkoYWxnYWVfc2FtcGxlc1tzYXBwbHkoYWxnYWVfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJG9jY3VycmVuY2VJRCkKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRvdGhlckNhdGFsb2dOdW1iZXJzKQojIGNsYXNzKGFsZ2FlX3NhbXBsZXMkb3JnYW5pc21TY29wZSkKIyBjbGFzcyhhbGdhZV9zYW1wbGVzJGV2ZW50SUQpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRzY2llbnRpZmljTmFtZSkgI2V2ZW50dWFsbHkgcGFyc2UgdGhpcyBpbnRvIHRheG9uIGNhdGVnb3JpZXM/CiMgY2xhc3MoYWxnYWVfc2FtcGxlcyR0YXhvblJhbmspICMgTWVsaW5kYSBuZWVkcyB0byBwb3B1bGF0ZSB0aGlzLi4uCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRpZGVudGlmaWVkQnkpCiMgY2xhc3MoYWxnYWVfc2FtcGxlcyRpbmRpdmlkdWFsQ291bnQpCgphbGdhZV9zYW1wbGVzJGJhc2lzb2ZSZWNvcmQ8LSJzcGVjaW1lbiIKYWxnYWVfc2FtcGxlcyRpbnN0aXR1dGlvbklEPC0iVVNOTSIKCgoKYGBgCgoKCgojIyMgSm9pbiB0aGUgZXZlbnQgZGF0YSBvbnRvIHRoZSBvY2N1cnJlbmNlIGRhdGEKCmBgYHtyIGpvaW4gYWxnYWV9CgphbGdhZTwtbGVmdF9qb2luKGFsZ2FlX3NhbXBsZXMsZXZlbnRzLGJ5PSJldmVudElEIikKCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgYWxnYWUgbWFwc30KCgojYnkgaW5kaXZpZHVhbAphbGdhZTI8LWFsZ2FlICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoY291bnQ9bigpKSAKCiNieSBzcGVjaWVzCmFsZ2FlMyA8LSBhbGdhZVstd2hpY2goYWxnYWUkc2NpZW50aWZpY05hbWU9PSI/IiksXSAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKYWxnYWU0PC1hbGdhZTMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCmFsZ2FlNTwtbGVmdF9qb2luKGFsZ2FlMixhbGdhZTQpCgojYWxnYWU1PC1hbGdhZTVbd2hpY2goaXMubmEoYWxnYWU1JGRlY2ltYWxMYXRpdHVkZSkpLF0KI2FsZ2FlNTwtYWxnYWU1Wy13aGljaChhbGdhZTUkc2NpZW50aWZpY05hbWU9PSI/IiksXQoKYWxnYWU1WzQsNF08LTEKYWxnYWU1WzExLDRdPC0yCmV4dHJhPC1hbGdhZTVbMzMsXQphbGdhZTU8LWFsZ2FlNVstMzMsXSAjcmVtb3ZlIG91dGxpZXIKCgphbGdhZV9tYXA8LWdnbWFwKGRtYXApICsgZ2VvbV9wb2ludChkYXRhID0gYWxnYWU1LCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWNvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlR5cGUgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsgZ2VvbV9wb2ludChkYXRhPWV4dHJhLCBtYXBwaW5nPWFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT0zMCwgY29sb3I9MzApKQojYWRkIG91dGxpZXIgYmFjayBpbiBhcyBhIHJlZCBkb3Qgc2l6ZT0zMAoKYWxnYWVfbWFwCgpnZ3NhdmUoYWxnYWVfbWFwLGZpbGVuYW1lPSIuL291dHB1dC9hbGdhZV9tYXAucGRmIikKYGBgCgojIyBNYWNyb2ludmVydGVicmF0ZXMKCiMjIyBJbXBvcnQKYGBge3IgaW52ZXJ0cyBpbXBvcnR9CmludmVydF9zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vSW52ZXJ0cy9CS0FORV8wNjMwMTdfRklNUy54bHN4Iiwgc2hlZXQgPSAiU3BlY2ltZW4iLHNraXA9MykKCiNzcG9uZ2VzIHdpbGwgYmUgbG9hZGVkIGhlcmUsIGNsZWFuZWQgdXAsIGFuZCB0aGVuIGpvaW5lZCB3aXRoIHRoZSByZXN0IG9mIHRoZSBpbnZlcnRzCnNwb25nZV9zYW1wbGVzPC1yZWFkX2V4Y2VsKHBhdGg9Ii9Vc2Vycy9lcmljL2dvb2dsZV9kcml2ZS9NYXJpbmVHRU8vU3Bvbmdlcy9WSUNFTlRFX0JJT0JMSVRaMjAxN19TUE9OR0VNRVRBREFUQV9GSU1TLnhsc3giLCBzaGVldCA9ICJTaGVldDEiLHNraXA9MSkKCiNyZW1vdmUgY29sdW1ucyB0aGF0IGRvbid0IGFwcGVhciBpbiBNYXJpbmVHRU8gc2NoZW1hCmludmVydF9zYW1wbGVzPC1pbnZlcnRfc2FtcGxlc1ssLWdyZXAocGF0dGVybiA9ICJeWCIseCA9IG5hbWVzKGludmVydF9zYW1wbGVzKSxwZXJsPVQpXQpzcG9uZ2Vfc2FtcGxlczwtc3BvbmdlX3NhbXBsZXNbLC1ncmVwKHBhdHRlcm4gPSAiXlgiLHggPSBuYW1lcyhzcG9uZ2Vfc2FtcGxlcykscGVybD1UKV0KCiNyZW1vdmUgcmVjb3JkcyB3aXRob3V0IG9jY3VycmVuY2VJRHMgKHRlbXAgYmVmb3JlIGZpbmFsIGRhdGFzZXQpCmludmVydF9zYW1wbGVzPC1pbnZlcnRfc2FtcGxlc1std2hpY2goaXMubmEoaW52ZXJ0X3NhbXBsZXMkc2NpZW50aWZpY05hbWUpKSxdCnNwb25nZV9zYW1wbGVzPC1zcG9uZ2Vfc2FtcGxlc1std2hpY2goaXMubmEoc3BvbmdlX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpKSxdCgojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MKaW52ZXJ0X3NhbXBsZXNbc2FwcGx5KGludmVydF9zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KGludmVydF9zYW1wbGVzW3NhcHBseShpbnZlcnRfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKCnNwb25nZV9zYW1wbGVzW3NhcHBseShzcG9uZ2Vfc2FtcGxlcywgaXMubG9naWNhbCldIDwtIGxhcHBseShzcG9uZ2Vfc2FtcGxlc1tzYXBwbHkoc3BvbmdlX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCnNwb25nZV9zYW1wbGVzJHBoeWx1bVt3aGljaChpcy5uYShzcG9uZ2Vfc2FtcGxlcyRwaHlsdW0pKV08LSJQb3JpZmVyYSIKc3BvbmdlX3NhbXBsZXMkZXZlbnRJRDwtc3RyX3JlcGxhY2Uoc3BvbmdlX3NhbXBsZXMkZXZlbnRJRCxwYXR0ZXJuPSItIiwgcmVwbGFjZW1lbnQ9IiIpCgoKaW52ZXJ0X3NhbXBsZXM8LWZ1bGxfam9pbihpbnZlcnRfc2FtcGxlcyxzcG9uZ2Vfc2FtcGxlcykKYGBgCgojIyMgVGF4b25vbWl6ZQoKVGhpcyBjb2RlIHdpbGwgcG9wdWxhdGUgYHRheG9uUmFua2Agd2l0aCB0aGUgbG93ZXN0IGtub3duIHRheG9ub21pYyBjYXRlZ29yeQoKYGBge3IgSW52ZXJ0cyBUYXhvbm9taXplfQoKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRwaHlsdW0pKV08LSJwaHlsdW0iCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkY2xhc3MpKV08LSJjbGFzcyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdWJjbGFzcykpXTwtInN1YmNsYXNzIgppbnZlcnRfc2FtcGxlcyR0YXhvblJhbmtbd2hpY2goIWlzLm5hKGludmVydF9zYW1wbGVzJG9yZGVyKSldPC0ib3JkZXIiCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkc3Vib3JkZXIpKV08LSJzdWJvcmRlciIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdXBlcmZhbWlseSkpXTwtInN1cGVyZmFtaWx5IgppbnZlcnRfc2FtcGxlcyR0YXhvblJhbmtbd2hpY2goIWlzLm5hKGludmVydF9zYW1wbGVzJGZhbWlseSkpXTwtImZhbWlseSIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzdWJmYW1pbHkpKV08LSJzdWJmYW1pbHkiCmludmVydF9zYW1wbGVzJHRheG9uUmFua1t3aGljaCghaXMubmEoaW52ZXJ0X3NhbXBsZXMkZ2VudXMpKV08LSJnZW51cyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW3doaWNoKCFpcy5uYShpbnZlcnRfc2FtcGxlcyRzcGVjaWVzKSldPC0ic3BlY2llcyIKaW52ZXJ0X3NhbXBsZXMkdGF4b25SYW5rW2dyZXAoInNwXFwuIixpbnZlcnRfc2FtcGxlcyRzcGVjaWVzKV08LSJnZW51cyIKCgoKYGBgCgoKIyMjIEZvcm1hdCBzYW1wbGVzIHRvIHNjaGVtYQoKYGBge3IgZm9ybWF0IGludmVydCBzYW1wbGVzfQojY2hhbmdlIGFsbCBlbXB0eSBjb2x1bW5zIGZyb20gbG9naWNhbCB0byBjaGFyYWN0ZXIgY2xhc3MgbW92ZWQgdGhpcyB1cAojaW52ZXJ0X3NhbXBsZXNbc2FwcGx5KGludmVydF9zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gI2xhcHBseShpbnZlcnRfc2FtcGxlc1tzYXBwbHkoaW52ZXJ0X3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiMgY2xhc3MoaW52ZXJ0X3NhbXBsZXMkb2NjdXJyZW5jZUlEKQojIGNsYXNzKGludmVydF9zYW1wbGVzJHNjaWVudGlmaWNOYW1lKSAjZXZlbnR1YWxseSBwYXJzZSB0aGlzIGludG8gdGF4b24gY2F0ZWdvcmllcz8KIyBjbGFzcyhpbnZlcnRfc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCgppbnZlcnRfc2FtcGxlcyRiYXNpc09mUmVjb3JkPC0ic3BlY2ltZW4iCmludmVydF9zYW1wbGVzJG9yZ2FuaXNtU2NvcGU8LSJvcmdhbmlzbSIKCiNyZW1vdmUgZXZlbnRJRHMgdGhhdCBoYXZlIHR3byBwb3NzaWJpbGl0aWVzLCBhc3N1bWUgaXQgaXMgdGhlIGZpcnN0IG9uZSBmb3Igbm93CmludmVydF9zYW1wbGVzJGV2ZW50SUQ8LWdzdWIocGF0dGVybj0iKFxcdykgb3IgXFx3IixyZXBsYWNlbWVudD0iXFwxIix4PSBpbnZlcnRfc2FtcGxlcyRldmVudElELHBlcmw9VCkKCiNmaXggYXJtcyBldmVudElEcwppbnZlcnRfc2FtcGxlcyRldmVudElEW2dyZXAocGF0dGVybj0iS0FORU8iLGludmVydF9zYW1wbGVzJGV2ZW50SUQpXTwtc3RyX3JlcGxhY2Uoc3RyaW5nPWludmVydF9zYW1wbGVzJGV2ZW50SURbZ3JlcChwYXR0ZXJuPSJLQU5FTyIsaW52ZXJ0X3NhbXBsZXMkZXZlbnRJRCldLHBhdHRlcm49IktBTkVPXFxkKFxcZFxcZCkiLCByZXBsYWNlbWVudD0iS0FORU9fMjAxN19BUk1TXFwxIikKCgppbnZlcnRfc2FtcGxlcyRpZGVudGlmaWVkQnk8LSJQYXVsYXksIEd1c3RhdiIgIyBmb3Igbm93LiBkb24ndCBrbm93IGlmIHRoZXkga2VwdCB0aGlzIGluZm8KI2Fzc3VtZSB0aGF0IGJsYW5rIGNvdW50cyBoYWQgMSBpbmRpdmlkdWFsIGZvciBub3cKaW52ZXJ0X3NhbXBsZXMkaW5kaXZpZHVhbENvdW50W2lzLm5hKGludmVydF9zYW1wbGVzJGluZGl2aWR1YWxDb3VudCldPC0xCmludmVydF9zYW1wbGVzJGluc3RpdHV0aW9uSUQ8LSJGTE1OSCIKCgoKYGBgCgojIyMgSm9pbiB0aGUgZXZlbnQgZGF0YSBvbnRvIHRoZSBvY2N1cnJlbmNlIGRhdGEKCmBgYHtyIGludmVydCBqb2lufQppbnZlcnQ8LWxlZnRfam9pbihpbnZlcnRfc2FtcGxlcyxldmVudHMsYnk9ImV2ZW50SUQiKQpgYGAKCiMjIyBNYWtlIEEgTWFwCmBgYHtyIGludmVydCBtYXBzfQojYnkgaW5kaXZpZHVhbAppbnZlcnQyPC1pbnZlcnQgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShpbmRpdmlkdWFsQ291bnQ9c3VtKGluZGl2aWR1YWxDb3VudCxuYS5ybSA9IFQpKSAKCiNieSBzcGVjaWVzCmludmVydDMgPC0gaW52ZXJ0ICU+JSBncm91cF9ieShzY2llbnRpZmljTmFtZSwgZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGNvdW50PW4oKSkKCiNyaWNobmVzcwppbnZlcnQ0PC1pbnZlcnQzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgppbnZlcnQ1PC1sZWZ0X2pvaW4oaW52ZXJ0MixpbnZlcnQ0KQoKCgoKaW52ZXJ0X21hcDwtZ2dtYXAoZG1hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBpbnZlcnQ1Wy1jKGxlbmd0aChpbnZlcnQ1JHJpY2huZXNzKS0xLGxlbmd0aChpbnZlcnQ1JHJpY2huZXNzKSksXSwgbWFwcGluZyA9IGFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT1pbmRpdmlkdWFsQ291bnQsIGNvbG9yPXJpY2huZXNzKSkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiZ3JlZW4iLCBoaWdoPSJyZWQiKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZT0iVHlwZSBSaWNobmVzcyIsKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9IkluZGl2aWR1YWwgQ291bnQiKSkgKyB0aGVtZShheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgCgppbnZlcnRfbWFwCgpnZ3NhdmUoaW52ZXJ0X21hcCxmaWxlbmFtZT0iLi9vdXRwdXQvaW52ZXJ0X21hcC5wZGYiKQoKI2NyZWF0ZSBhIHZlY3RvciBvZiB0aGUgZXZlbnRJRHMgbm90IGZpbmRpbmcgYSBtYXRjaCBpbiB0aGUgZXZlbnRzIGRhdGFiYXNlCmJhZF9ldmVudElEczwtaW52ZXJ0JGV2ZW50SURbd2hpY2goaXMubmEoaW52ZXJ0JGRlY2ltYWxMYXRpdHVkZSkpXQpgYGAKCiMjIyBNYWtlIEEgU3BvbmdlIE1hcAoKYGBge3Igc3BvbmdlIG1hcHN9CnNwb25nZTwtaW52ZXJ0W3doaWNoKGludmVydCRwaHlsdW09PSJQb3JpZmVyYSIpLF0KI2J5IGluZGl2aWR1YWwKc3BvbmdlMjwtc3BvbmdlICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoaW5kaXZpZHVhbENvdW50PXN1bShpbmRpdmlkdWFsQ291bnQsbmEucm0gPSBUKSkgCgojYnkgc3BlY2llcwpzcG9uZ2UzIDwtIHNwb25nZSAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKc3BvbmdlNDwtc3BvbmdlMyAlPiUgZ3JvdXBfYnkoZGVjaW1hbExhdGl0dWRlLGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUocmljaG5lc3M9bigpKQoKc3BvbmdlNTwtbGVmdF9qb2luKHNwb25nZTIsc3BvbmdlNCkKCgoKc3BvbmdlX21hcDwtZ2dtYXAoZG1hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBzcG9uZ2U1Wy1jKDYxLDYyKSxdLCBtYXBwaW5nID0gYWVzKHggPSBkZWNpbWFsTG9uZ2l0dWRlLCB5ID0gZGVjaW1hbExhdGl0dWRlLCBzaXplPWluZGl2aWR1YWxDb3VudCwgY29sb3I9cmljaG5lc3MpKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJncmVlbiIsIGhpZ2g9InJlZCIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlPSJUeXBlIFJpY2huZXNzIiwpLCBzaXplPWd1aWRlX2xlZ2VuZCh0aXRsZT0iSW5kaXZpZHVhbCBDb3VudCIpKSArIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpKSAKCnNwb25nZV9tYXAKCmdnc2F2ZShzcG9uZ2VfbWFwLGZpbGVuYW1lPSIuL291dHB1dC9zcG9uZ2VfbWFwLnBkZiIpCgpgYGAKCiMjIE1laW9mYXVuYQoKIyMjIEltcG9ydApgYGB7ciBpbXBvcnQgbWVpb2ZhdW5hfQojbm90ZSBtZWlvIGRhdGEgc3RpbGwgbmVlZCBzb21lIGNsZWFuaW5nLCBpbmNsdWRpbmcgaW1wb3J0aW5nIHNvbWUgc3RhdGlvbnMgZnJvbSBpbnZlcnRzIGFuZCBmaXNoLCBhbmQgZml4aW5nIHVwIGV2ZW50SURzIHRvIGhhdmUgMyBkaWdpdHMgaW5zdGVhZCBvZiAyLiBUaGVyZSBhcmUgMjcgc3BlY2ltZW5zIHRoYXQgZG8gbm90IGhhdmUgc3RhdGlvbiBpbmZvcm1hdGlvbiBiZWNhdXNlIG9mIHRoaXMuCgptZWlvX3NhbXBsZXM8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9NZWlvZmF1bmEvSGF3YWlpMjAxN19tZWlvZmF1bmFfTWFyaW5lR0VPLnhsc3giLCBzaGVldCA9ICJzcGVjaW1lbiBkYXRhIixza2lwPTEpCgojcmVtb3ZlIGNvbHVtbnMgdGhhdCBkb24ndCBhcHBlYXIgaW4gTWFyaW5lR0VPIHNjaGVtYQptZWlvX3NhbXBsZXM8LW1laW9fc2FtcGxlc1ssLWdyZXAocGF0dGVybiA9ICJeWCIseCA9IG5hbWVzKG1laW9fc2FtcGxlcykscGVybD1UKV0KCiNhZGQgb2NjdXJyZW5jZSBJRHMgdG8gb25lIGludmVzdGlnYXRvcnMgc2FtcGxlcyAtIHRoaXMgaGFzIGJlZW4gdGFrZW4gY2FyZSBvZiBub3cKI21laW9fc2FtcGxlcyRvY2N1cnJlbmNlSURbd2hpY2goaXMubmEobWVpb19zYW1wbGVzJG9jY3VycmVuY2VJRCkpXTwtIlVKIiAKI21ha2Ugb2NjdXJyZW5jZSBJRHMgdW5pcXVlCiNtZWlvX3NhbXBsZXMkb2NjdXJyZW5jZUlEPC1tYWtlLnVuaXF1ZShtZWlvX3NhbXBsZXMkb2NjdXJyZW5jZUlELCBzZXA9Il8iKQoKCmBgYAoKCiMjIyBGb3JtYXQgc2FtcGxlcyB0byBzY2hlbWEKCmBgYHtyIGZvcm1hdCBtZWlvZmF1bmEgc2FtcGxlc30KI2NoYW5nZSBhbGwgZW1wdHkgY29sdW1ucyBmcm9tIGxvZ2ljYWwgdG8gY2hhcmFjdGVyIGNsYXNzCm1laW9fc2FtcGxlc1tzYXBwbHkobWVpb19zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KG1laW9fc2FtcGxlc1tzYXBwbHkobWVpb19zYW1wbGVzLCBpcy5sb2dpY2FsKV0sICBhcy5jaGFyYWN0ZXIpCgptZWlvX3NhbXBsZXMkYmFzaXNvZlJlY29yZDwtInNwZWNpbWVuIiAjY2hlY2sgd2l0aCBGcmV5IHRoYXQgdGhpcyBpcyBjb3JyZWN0Cm1laW9fc2FtcGxlcyRpbnN0aXR1dGlvbklEPC0iVVNOTSIKCiMgY2xhc3MobWVpb19zYW1wbGVzJHNjaWVudGlmaWNOYW1lKSAjZXZlbnR1YWxseSBwYXJzZSB0aGlzIGludG8gdGF4b24gY2F0ZWdvcmllcz8KIyBjbGFzcyhtZWlvX3NhbXBsZXMkdGF4b25SYW5rKSAjdXNpbmcgdGhpcwojIGNsYXNzKG1laW9fc2FtcGxlcyRvY2N1cnJlbmNlSUQpCiMgY2xhc3MobWVpb19zYW1wbGVzJGNhdGFsb2dOdW1iZXIpCiMgY2xhc3MobWVpb19zYW1wbGVzJG90aGVyQ2F0YWxvZ051bWJlcnMpCiMgY2xhc3MobWVpb19zYW1wbGVzJG9yZ2FuaXNtU2NvcGUpCiMgY2xhc3MobWVpb19zYW1wbGVzJGV2ZW50SUQpCiMgY2xhc3MobWVpb19zYW1wbGVzJGlkZW50aWZpZWRCeSkKIyBjbGFzcyhtZWlvX3NhbXBsZXMkaW5kaXZpZHVhbENvdW50KQoKCmBgYAoKIyMjIEpvaW4gdGhlIGV2ZW50IGRhdGEgb250byB0aGUgb2NjdXJyZW5jZSBkYXRhCgpgYGB7ciBtZWlvZmF1bmEgam9pbn0KbWVpbzwtbGVmdF9qb2luKG1laW9fc2FtcGxlcyxtZWlvX2V2ZW50cyxieT0iZXZlbnRJRCIpCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgbWVpb2ZhdW5hIG1hcHN9CiNieSBpbmRpdmlkdWFsCm1laW8yPC1tZWlvICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsIGRlY2ltYWxMb25naXR1ZGUpICU+JSBzdW1tYXJpemUoaW5kaXZpZHVhbENvdW50PXN1bShpbmRpdmlkdWFsQ291bnQsbmEucm0gPSBUKSkgCgojYnkgc3BlY2llcwptZWlvMyA8LSBtZWlvICU+JSBncm91cF9ieShzY2llbnRpZmljTmFtZSwgZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGNvdW50PW4oKSkKCiNyaWNobmVzcwptZWlvNDwtbWVpbzMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSxkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKHJpY2huZXNzPW4oKSkKCm1laW81PC1sZWZ0X2pvaW4obWVpbzIsbWVpbzQpCgoKCgptZWlvX21hcDwtZ2dtYXAoZG1hcCkgKyBnZW9tX3BvaW50KGRhdGEgPSBtZWlvNSwgbWFwcGluZyA9IGFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT1pbmRpdmlkdWFsQ291bnQsIGNvbG9yPXJpY2huZXNzKSkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiZ3JlZW4iLCBoaWdoPSJyZWQiKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZT0iVHlwZSBSaWNobmVzcyIsKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9IkluZGl2aWR1YWwgQ291bnQiKSkgKyB0aGVtZShheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgCgptZWlvX21hcAoKZ2dzYXZlKG1laW9fbWFwLGZpbGVuYW1lPSIuL291dHB1dC9tZWlvX21hcC5wZGYiKQpgYGAKCiMjIEFSTVMKCiMjIyBJbXBvcnQKYGBge3IgaW1wb3J0IGFybXN9CmFybXNfc2FtcGxlczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL0FSTVMvTWFyaW5lR0VPSElfYmlvYXNzZXNzbWVudF9tYXN0ZXItQVJNUy54bHN4Iiwgc2hlZXQgPSAiU2FtcGxlIikKCmBgYAoKCiMjIyBGb3JtYXQgc2FtcGxlcyB0byBzY2hlbWEKCmBgYHtyIGZvcm1hdCBhcm1zIHNhbXBsZXN9CiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwphcm1zX3NhbXBsZXNbc2FwcGx5KGFybXNfc2FtcGxlcywgaXMubG9naWNhbCldIDwtIGxhcHBseShhcm1zX3NhbXBsZXNbc2FwcGx5KGFybXNfc2FtcGxlcywgaXMubG9naWNhbCldLCAgYXMuY2hhcmFjdGVyKQoKIyBjbGFzcyhhcm1zX3NhbXBsZXMkb2NjdXJyZW5jZUlEKQojIGNsYXNzKGFybXNfc2FtcGxlcyRiYXNpc29mUmVjb3JkKQojIGNsYXNzKGFybXNfc2FtcGxlcyRjYXRhbG9nTnVtYmVyKQojIGNsYXNzKGFybXNfc2FtcGxlcyRvdGhlckNhdGFsb2dOdW1iZXJzKQojIGNsYXNzKGFybXNfc2FtcGxlcyRvcmdhbmlzbVNjb3BlKSAjd2VyZSB0aGVyZSBzb21lIHNsdXJyaWVzIHRvbz8KIyBjbGFzcyhhcm1zX3NhbXBsZXMkZXZlbnRJRCkKIyBjbGFzcyhhcm1zX3NhbXBsZXMkc2NpZW50aWZpY05hbWUpICNldmVudHVhbGx5IHBhcnNlIHRoaXMgaW50byB0YXhvbiBjYXRlZ29yaWVzPwojIGNsYXNzKGFybXNfc2FtcGxlcyR0YXhvblJhbmspICN1c2luZyB0aGlzCiMgY2xhc3MoYXJtc19zYW1wbGVzJGlkZW50aWZpZWRCeSkKIyBjbGFzcyhhcm1zX3NhbXBsZXMkaW5kaXZpZHVhbENvdW50KQoKIyBjaGFuZ2UgTkFzIGZvciBpbmRpdmlkdWFsQ291bnQgdG8gMSBmb3Igbm93CmFybXNfc2FtcGxlcyRpbmRpdmlkdWFsQ291bnRbd2hpY2goaXMubmEoYXJtc19zYW1wbGVzJGluZGl2aWR1YWxDb3VudCkpXTwtMQoKYXJtc19zYW1wbGVzJGluc3RpdHV0aW9uSUQ8LSJVU05NIgoKYGBgCgojIyMgSm9pbiB0aGUgZXZlbnQgZGF0YSBvbnRvIHRoZSBvY2N1cnJlbmNlIGRhdGEKCmBgYHtyIGFybXMgam9pbn0KYXJtczwtbGVmdF9qb2luKGFybXNfc2FtcGxlcyxhcm1zX2V2ZW50cyxieT0iZXZlbnRJRCIpCmBgYAoKIyMjIE1ha2UgQSBNYXAKYGBge3IgYXJtcyBtYXBzfQojYnkgaW5kaXZpZHVhbAphcm1zMjwtYXJtcyAlPiUgZ3JvdXBfYnkoZGVjaW1hbExhdGl0dWRlLCBkZWNpbWFsTG9uZ2l0dWRlKSAlPiUgc3VtbWFyaXplKGluZGl2aWR1YWxDb3VudD1zdW0oaW5kaXZpZHVhbENvdW50LG5hLnJtID0gVCkpIAoKI2J5IHNwZWNpZXMKYXJtczMgPC0gYXJtcyAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCkpCgojcmljaG5lc3MKYXJtczQ8LWFybXMzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgphcm1zNTwtbGVmdF9qb2luKGFybXMyLGFybXM0KQoKCgoKYXJtc19tYXA8LWdnbWFwKGRtYXApICsgZ2VvbV9wb2ludChkYXRhID0gYXJtczUsIG1hcHBpbmcgPSBhZXMoeCA9IGRlY2ltYWxMb25naXR1ZGUsIHkgPSBkZWNpbWFsTGF0aXR1ZGUsIHNpemU9aW5kaXZpZHVhbENvdW50LCBjb2xvcj1yaWNobmVzcykpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gImdyZWVuIiwgaGlnaD0icmVkIikgKyBndWlkZXMoY29sb3I9Z3VpZGVfY29sb3JiYXIodGl0bGU9IlR5cGUgUmljaG5lc3MiLCksIHNpemU9Z3VpZGVfbGVnZW5kKHRpdGxlPSJJbmRpdmlkdWFsIENvdW50IikpICsgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkpIAoKYXJtc19tYXAKCmdnc2F2ZShhcm1zX21hcCxmaWxlbmFtZT0iLi9vdXRwdXQvYXJtc19tYXAucGRmIikKYGBgCgoKIyMgVmlzdWFsIFRyYW5zZWN0cwoKIyMjIEltcG9ydApgYGB7ciB0cmFuc2VjdHMgaW1wb3J0fQoKdHJhbnNfc2FtcGxlczwtcmVhZF9leGNlbChwYXRoPSIvVXNlcnMvZXJpYy9nb29nbGVfZHJpdmUvTWFyaW5lR0VPL1RyYW5zZWN0cy9iaW9hc3Nlc3NtZW50X0tBTlYueGxzeCIsIHNoZWV0ID0gIlNhbXBsZSIpCgp0cmFuc19vcmdhbmlzbV9waG90b3M8LXJlYWRfZXhjZWwocGF0aD0iL1VzZXJzL2VyaWMvZ29vZ2xlX2RyaXZlL01hcmluZUdFTy9UcmFuc2VjdHMvS0FOVl9waG90by12b3VjaGVyc18yMDE3MDcxMi54bHN4Iiwgc2hlZXQgPSAiU2hlZXQxIikKYGBgCgojIyMgRm9ybWF0LCBjb2xsYXBzZSBhbmQgbWVyZ2UgdGhlIG1lZGlhIGZpZWxkcwoKIyMjIE9yZ2FuaXNtIHBob3RvcwpgYGB7ciB0cmFuc2VjdCBwaG90byBmaWVsZHN9CiMgb3JnYW5pc20gcGhvdG9zCgojIyBkZWxldGUgdGhlIGZpZWxkIHRvIGJlIGFkZGVkIGxhdGVyCnRyYW5zX3NhbXBsZXMkYXNzb2NpYXRlZE1lZGlhPC1OVUxMCgojcG9wIG9mZiB0aGUgZXZlbnRJRCBhZ2FpbiBpbnRvIGl0cyBvd24gZmllbGQKdHJhbnNfb3JnYW5pc21fcGhvdG9zJGV2ZW50SUQ8LXN1YihwYXR0ZXJuPSIoS0FOVlxcZFxcZFxcZClfLisiLHJlcGxhY2VtZW50ID0gIlxcMSIsIHRyYW5zX29yZ2FuaXNtX3Bob3RvcyRhc3NvY2lhdGVkTWVkaWEsIHBlcmw9VCkKCiNwb3Agb2ZmIHRoZSBzcGVjaWVzIG5hbWUgaW50byBpdHMgb3duIGZpZWxkCnRyYW5zX29yZ2FuaXNtX3Bob3RvcyRzY2llbnRpZmljTmFtZTwtc3ViKHBhdHRlcm49Ii4rXyhcXGR7OH0pXyhcXHcrLVthLXpdKylfLisiLCByZXBsYWNlbWVudCA9ICJcXDIiLCB0cmFuc19vcmdhbmlzbV9waG90b3MkYXNzb2NpYXRlZE1lZGlhLHBlcmw9VCkKdHJhbnNfb3JnYW5pc21fcGhvdG9zJHNjaWVudGlmaWNOYW1lPC1zdWIocGF0dGVybj0iLSIsIHJlcGxhY2VtZW50PSIgIix4ID0gdHJhbnNfb3JnYW5pc21fcGhvdG9zJHNjaWVudGlmaWNOYW1lKQoKI3BvcCBvZmYgdGhlIGluaXRpYWxzIG9mIHRoZSBjb2xsZWN0b3IsIGFuZCByZXBsYWNlIHdpdGggZnVsbCBuYW1lCnRyYW5zX29yZ2FuaXNtX3Bob3RvcyRpZGVudGlmaWVkQnk8LXN0cl9leHRyYWN0KHBhdHRlcm49IlpGfFJXIiwgc3RyaW5nPXRyYW5zX29yZ2FuaXNtX3Bob3RvcyRhc3NvY2lhdGVkTWVkaWEpCnRyYW5zX29yZ2FuaXNtX3Bob3RvcyRpZGVudGlmaWVkQnlbd2hpY2godHJhbnNfb3JnYW5pc21fcGhvdG9zJGlkZW50aWZpZWRCeT09IlpGIildPC0iWmFjaCBGb2x0eiIKdHJhbnNfb3JnYW5pc21fcGhvdG9zJGlkZW50aWZpZWRCeVt3aGljaCh0cmFuc19vcmdhbmlzbV9waG90b3MkaWRlbnRpZmllZEJ5PT0iUlciKV08LSJSb3NzIFdoaXBwbyIKCiN1c2UgZGRwbHkgdG8gbHVtcCBhbGwgYXNzb2NpYXRlZE1lZGlhIGludG8gYSBzaW5nbGUgZmllbGQsIHNlcGFyYXRlZCBieSBhIHwKdHJhbnNfYXNzb2NpYXRlZE1lZGlhPC1kZHBseSh0cmFuc19vcmdhbmlzbV9waG90b3MsIGMoImV2ZW50SUQiLCJzY2llbnRpZmljTmFtZSIsImlkZW50aWZpZWRCeSIpLCB0cmFuc2Zvcm0sIGFzc29jaWF0ZWRNZWRpYSA9IHBhc3RlKGFzc29jaWF0ZWRNZWRpYSwgY29sbGFwc2UgPSAifCIpKQoKI3JlbW92ZSBhbGwgYnV0IHRoZSBmaXJzdCBpbnN0YW5jZQp0cmFuc19hc3NvY2lhdGVkTWVkaWE8LXRyYW5zX2Fzc29jaWF0ZWRNZWRpYVshZHVwbGljYXRlZCh0cmFuc19hc3NvY2lhdGVkTWVkaWEkYXNzb2NpYXRlZE1lZGlhKSxdCgp0cmFuc19zYW1wbGVzPC1sZWZ0X2pvaW4odHJhbnNfc2FtcGxlcywgdHJhbnNfYXNzb2NpYXRlZE1lZGlhLCBieT1jKCJldmVudElEIiwic2NpZW50aWZpY05hbWUiLCJpZGVudGlmaWVkQnkiKSkKCmBgYAoKIyMjIEZvcm1hdCBzYW1wbGVzIHRvIHNjaGVtYQoKYGBge3IgZm9ybWF0IHRyYW5zZWN0IHNhbXBsZXN9CiNjaGFuZ2UgYWxsIGVtcHR5IGNvbHVtbnMgZnJvbSBsb2dpY2FsIHRvIGNoYXJhY3RlciBjbGFzcwp0cmFuc19zYW1wbGVzW3NhcHBseSh0cmFuc19zYW1wbGVzLCBpcy5sb2dpY2FsKV0gPC0gbGFwcGx5KHRyYW5zX3NhbXBsZXNbc2FwcGx5KHRyYW5zX3NhbXBsZXMsIGlzLmxvZ2ljYWwpXSwgIGFzLmNoYXJhY3RlcikKCiMgY2xhc3ModHJhbnNfc2FtcGxlcyRvY2N1cnJlbmNlSUQpCiMgY2xhc3ModHJhbnNfc2FtcGxlcyRiYXNpc29mUmVjb3JkKQojIGNsYXNzKHRyYW5zX3NhbXBsZXMkY2F0YWxvZ051bWJlcikKIyBjbGFzcyh0cmFuc19zYW1wbGVzJG90aGVyQ2F0YWxvZ051bWJlcnMpCiMgY2xhc3ModHJhbnNfc2FtcGxlcyRvcmdhbmlzbVNjb3BlKQojIGNsYXNzKHRyYW5zX3NhbXBsZXMkZXZlbnRJRCkKIyBjbGFzcyh0cmFuc19zYW1wbGVzJHNjaWVudGlmaWNOYW1lKSAjZXZlbnR1YWxseSBwYXJzZSB0aGlzIGludG8gdGF4b24gY2F0ZWdvcmllcz8KIyBjbGFzcyh0cmFuc19zYW1wbGVzJHRheG9uUmFuaykgI3VzaW5nIHRoaXMKIyBjbGFzcyh0cmFuc19zYW1wbGVzJGlkZW50aWZpZWRCeSkKIyBjbGFzcyh0cmFuc19zYW1wbGVzJGluZGl2aWR1YWxDb3VudCkKCnRyYW5zX3NhbXBsZXMkaW5zdGl0dXRpb25JRDwtIlVTTk0iCgoKCgpgYGAKCiMjIyBKb2luIHRoZSBldmVudCBkYXRhIG9udG8gdGhlIG9jY3VycmVuY2UgZGF0YQoKYGBge3Igam9pbiB0cmFuc2VjdHN9CnRyYW5zPC1sZWZ0X2pvaW4odHJhbnNfc2FtcGxlcyx0cmFuc19ldmVudHMsYnk9ImV2ZW50SUQiKQpgYGAKCiMjIyBNYWtlIEEgTWFwCmBgYHtyIHRyYW5zZWN0IG1hcHN9CiNieSBpbmRpdmlkdWFsCnRyYW5zMjwtdHJhbnMgJT4lIGdyb3VwX2J5KGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShpbmRpdmlkdWFsQ291bnQ9c3VtKGluZGl2aWR1YWxDb3VudCxuYS5ybSA9IFQpKSAKCiNieSBzcGVjaWVzCnRyYW5zMyA8LSB0cmFucyAlPiUgZ3JvdXBfYnkoc2NpZW50aWZpY05hbWUsIGRlY2ltYWxMYXRpdHVkZSwgZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShjb3VudD1uKCksIGluZGl2aWR1YWxDb3VudD1zdW0oaW5kaXZpZHVhbENvdW50LG5hLnJtPVQpKQoKI3JpY2huZXNzCnRyYW5zNDwtdHJhbnMzICU+JSBncm91cF9ieShkZWNpbWFsTGF0aXR1ZGUsZGVjaW1hbExvbmdpdHVkZSkgJT4lIHN1bW1hcml6ZShyaWNobmVzcz1uKCkpCgp0cmFuczU8LWxlZnRfam9pbih0cmFuczIsdHJhbnM0KQoKCgoKdHJhbnNfbWFwPC1nZ21hcChkbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IHRyYW5zNSwgbWFwcGluZyA9IGFlcyh4ID0gZGVjaW1hbExvbmdpdHVkZSwgeSA9IGRlY2ltYWxMYXRpdHVkZSwgc2l6ZT1pbmRpdmlkdWFsQ291bnQsIGNvbG9yPXJpY2huZXNzKSkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAiZ3JlZW4iLCBoaWdoPSJyZWQiKSArIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZT0iU3BlY2llcyBSaWNobmVzcyIsKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9IkluZGl2aWR1YWwgQ291bnQiKSkgKyB0aGVtZShheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgCgp0cmFuc19tYXAKCmdnc2F2ZSh0cmFuc19tYXAsZmlsZW5hbWU9Ii4vb3V0cHV0L3RyYW5zX21hcC5wZGYiKQpgYGAKCiMgRmluYWwgRGF0YWJhc2UKCk5vdyB0byBqb2luIGV2ZXJ5dGhpbmcgaW50byBvbmUgbW9uc3RlciBkYXRhYmFzZQoKYGBge3J9CmE8LWZ1bGxfam9pbihmaXNoLGFsZ2FlKQpiPC1mdWxsX2pvaW4oYSxpbnZlcnQpCmM8LWZ1bGxfam9pbihiLG1laW8pCmQ8LWZ1bGxfam9pbihjLGFybXMpCk1hcmluZUdFT0hJPC1mdWxsX2pvaW4oZCx0cmFucykKCiNyZWFkIGluIHRoZSBmbGF0IHNjaGVtYQpmbGF0X3NjaGVtYTwtYXMudmVjdG9yKHJlYWQuY3N2KCJmbGF0X3NjaGVtYS5jc3YiLCBoZWFkZXI9Riwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpKQoKI3JlZHVjZSB0aGUgam9pbmVkIGRhdGFiYXNlIHRvIGp1c3QgdGhlIGNvbHVtbnMgaW4gdGhlIHNjaGVtYSwgYW5kIHNvcnQgb24gY29sdW1uIG9yZGVyCk1hcmluZUdFT0hJMjwtTWFyaW5lR0VPSElbLG1hdGNoKGZsYXRfc2NoZW1hLCBuYW1lcyhNYXJpbmVHRU9ISSkpXQoKd3JpdGUuY3N2KE1hcmluZUdFT0hJMiwiLi9vdXRwdXQvTWFyaW5lR0VPSElfZGF0YV8xLjEuY3N2Iixyb3cubmFtZXMgPSBGKQoKI1dyaXRlWExTKGMoTWFyaW5lR0VPSEkyLGFzLmRhdGEuZnJhbWUoZXZlbnRzKSksRXhjZWxGaWxlTmFtZSA9ICIuL291dHB1dC9NYXJpbmVHRU9ISV9kYXRhXzEuMS54bHN4IixTaGVldE5hbWVzPWMoIkV2ZW50cyIsIlNhbXBsZXMiKSkKCmBgYA==